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 "common_event_manager_service.h"
17
18 #include "ability_manager_helper.h"
19 #include "access_token_helper.h"
20 #include "accesstoken_kit.h"
21 #include "bundle_manager_helper.h"
22 #include "common_event_constant.h"
23 #include "datetime_ex.h"
24 #include "event_log_wrapper.h"
25 #include "hitrace_meter_adapter.h"
26 #include "ipc_skeleton.h"
27 #include "parameters.h"
28 #include "publish_manager.h"
29 #include "system_ability_definition.h"
30 #include "xcollie/watchdog.h"
31 #include "ces_inner_error_code.h"
32
33 namespace OHOS {
34 namespace EventFwk {
35 namespace {
36 const std::string NOTIFICATION_CES_CHECK_SA_PERMISSION = "notification.ces.check.sa.permission";
37 } // namespace
38
39 using namespace OHOS::Notification;
40
CommonEventManagerService()41 CommonEventManagerService::CommonEventManagerService()
42 : serviceRunningState_(ServiceRunningState::STATE_NOT_START),
43 runner_(nullptr),
44 handler_(nullptr)
45 {
46 supportCheckSaPermission_ = OHOS::system::GetParameter(NOTIFICATION_CES_CHECK_SA_PERMISSION, "false");
47 EVENT_LOGD("instance created");
48 }
49
~CommonEventManagerService()50 CommonEventManagerService::~CommonEventManagerService()
51 {
52 EVENT_LOGD("instance destroyed");
53 }
54
Init()55 ErrCode CommonEventManagerService::Init()
56 {
57 EVENT_LOGD("ready to init");
58 innerCommonEventManager_ = std::make_shared<InnerCommonEventManager>();
59 if (!innerCommonEventManager_) {
60 EVENT_LOGE("Failed to init without inner service");
61 return ERR_INVALID_OPERATION;
62 }
63
64 commonEventSrvQueue_ = std::make_shared<ffrt::queue>("CesSrvMain");
65 serviceRunningState_ = ServiceRunningState::STATE_RUNNING;
66
67 return ERR_OK;
68 }
69
IsReady() const70 bool CommonEventManagerService::IsReady() const
71 {
72 if (!innerCommonEventManager_) {
73 EVENT_LOGE("innerCommonEventManager is null");
74 return false;
75 }
76
77 if (!commonEventSrvQueue_) {
78 EVENT_LOGE("queue object is null");
79 return false;
80 }
81
82 return true;
83 }
84
PublishCommonEvent(const CommonEventData & event,const CommonEventPublishInfo & publishinfo,const sptr<IRemoteObject> & commonEventListener,const int32_t & userId)85 int32_t CommonEventManagerService::PublishCommonEvent(const CommonEventData &event,
86 const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener,
87 const int32_t &userId)
88 {
89 EVENT_LOGD("enter");
90
91 if (!IsReady()) {
92 EVENT_LOGE("CommonEventManagerService not ready");
93 return ERR_NOTIFICATION_CESM_ERROR;
94 }
95
96 if (userId != ALL_USER && userId != CURRENT_USER && userId != UNDEFINED_USER) {
97 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
98 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
99 EVENT_LOGE("publish to special user must be system application.");
100 return ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP;
101 }
102 }
103
104 return PublishCommonEventDetailed(event,
105 publishinfo,
106 commonEventListener,
107 IPCSkeleton::GetCallingPid(),
108 IPCSkeleton::GetCallingUid(),
109 IPCSkeleton::GetCallingTokenID(),
110 userId);
111 }
112
PublishCommonEvent(const CommonEventData & event,const CommonEventPublishInfo & publishinfo,const sptr<IRemoteObject> & commonEventListener,const uid_t & uid,const int32_t & callerToken,const int32_t & userId)113 bool CommonEventManagerService::PublishCommonEvent(const CommonEventData &event,
114 const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener, const uid_t &uid,
115 const int32_t &callerToken, const int32_t &userId)
116 {
117 EVENT_LOGD("enter");
118
119 if (!IsReady()) {
120 EVENT_LOGE("CommonEventManagerService not ready");
121 return false;
122 }
123
124 if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
125 EVENT_LOGE("Only sa can publish common event as proxy.");
126 return false;
127 }
128
129 return PublishCommonEventDetailed(
130 event, publishinfo, commonEventListener, UNDEFINED_PID, uid, callerToken, userId) == ERR_OK ? true : false;
131 }
132
PublishCommonEventDetailed(const CommonEventData & event,const CommonEventPublishInfo & publishinfo,const sptr<IRemoteObject> & commonEventListener,const pid_t & pid,const uid_t & uid,const int32_t & clientToken,const int32_t & userId)133 int32_t CommonEventManagerService::PublishCommonEventDetailed(const CommonEventData &event,
134 const CommonEventPublishInfo &publishinfo, const sptr<IRemoteObject> &commonEventListener, const pid_t &pid,
135 const uid_t &uid, const int32_t &clientToken, const int32_t &userId)
136 {
137 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
138
139 EVENT_LOGD("clientToken = %{public}d", clientToken);
140 if (AccessTokenHelper::IsDlpHap(clientToken)) {
141 EVENT_LOGE("DLP hap not allowed to send common event");
142 return ERR_NOTIFICATION_CES_NOT_SA_SYSTEM_APP;
143 }
144 struct tm recordTime = {0};
145 if (!GetSystemCurrentTime(&recordTime)) {
146 EVENT_LOGE("Failed to GetSystemCurrentTime");
147 return ERR_NOTIFICATION_SYS_ERROR;
148 }
149
150 if (DelayedSingleton<PublishManager>::GetInstance()->CheckIsFloodAttack(uid)) {
151 EVENT_LOGE("Too many common events have been sent in a short period from (pid = %{public}d, uid = "
152 "%{public}d, userId = %{public}d)",
153 pid,
154 uid,
155 userId);
156 return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
157 }
158
159 std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
160 wptr<CommonEventManagerService> weakThis = this;
161 std::function<void()> publishCommonEventFunc = [wp,
162 event,
163 publishinfo,
164 commonEventListener,
165 recordTime,
166 pid,
167 uid,
168 clientToken,
169 userId,
170 weakThis] () {
171 std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
172 if (innerCommonEventManager == nullptr) {
173 EVENT_LOGE("innerCommonEventManager not exist");
174 return;
175 }
176 std::string bundleName = DelayedSingleton<BundleManagerHelper>::GetInstance()->GetBundleName(uid);
177 sptr<CommonEventManagerService> commonEventManagerService = weakThis.promote();
178 if (commonEventManagerService == nullptr) {
179 EVENT_LOGE("CommonEventManager not exist");
180 return;
181 }
182 bool ret = innerCommonEventManager->PublishCommonEvent(event,
183 publishinfo,
184 commonEventListener,
185 recordTime,
186 pid,
187 uid,
188 clientToken,
189 userId,
190 bundleName,
191 commonEventManagerService);
192 if (!ret) {
193 EVENT_LOGE("failed to publish event %{public}s", event.GetWant().GetAction().c_str());
194 }
195 };
196 EVENT_LOGD("start to submit publish commonEvent <%{public}d>", uid);
197 commonEventSrvQueue_->submit(publishCommonEventFunc);
198 return ERR_OK;
199 }
200
SubscribeCommonEvent(const CommonEventSubscribeInfo & subscribeInfo,const sptr<IRemoteObject> & commonEventListener)201 int32_t CommonEventManagerService::SubscribeCommonEvent(
202 const CommonEventSubscribeInfo &subscribeInfo, const sptr<IRemoteObject> &commonEventListener)
203 {
204 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
205 EVENT_LOGD("enter");
206
207 if (!IsReady()) {
208 EVENT_LOGE("CommonEventManagerService not ready");
209 return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
210 }
211
212 struct tm recordTime = {0};
213 if (!GetSystemCurrentTime(&recordTime)) {
214 EVENT_LOGE("Failed to GetSystemCurrentTime");
215 return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
216 }
217
218 auto callingUid = IPCSkeleton::GetCallingUid();
219 auto callingPid = IPCSkeleton::GetCallingPid();
220 std::string bundleName = DelayedSingleton<BundleManagerHelper>::GetInstance()->GetBundleName(callingUid);
221 Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
222 std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
223 std::function<void()> subscribeCommonEventFunc = [wp,
224 subscribeInfo,
225 commonEventListener,
226 recordTime,
227 callingPid,
228 callingUid,
229 callerToken,
230 bundleName] () {
231 std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
232 if (innerCommonEventManager == nullptr) {
233 EVENT_LOGE("innerCommonEventManager not exist");
234 return;
235 }
236 bool ret = innerCommonEventManager->SubscribeCommonEvent(subscribeInfo,
237 commonEventListener,
238 recordTime,
239 callingPid,
240 callingUid,
241 callerToken,
242 bundleName);
243 if (!ret) {
244 EVENT_LOGE("failed to subscribe event");
245 }
246 };
247
248 EVENT_LOGD("start to submit subscribe commonEvent <%{public}d>", callingUid);
249 commonEventSrvQueue_->submit(subscribeCommonEventFunc);
250 return ERR_OK;
251 }
252
UnsubscribeCommonEvent(const sptr<IRemoteObject> & commonEventListener)253 int32_t CommonEventManagerService::UnsubscribeCommonEvent(const sptr<IRemoteObject> &commonEventListener)
254 {
255 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
256 EVENT_LOGD("enter");
257
258 if (!IsReady()) {
259 EVENT_LOGE("CommonEventManagerService not ready");
260 return ERR_NOTIFICATION_CES_COMMON_PARAM_INVALID;
261 }
262
263 std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
264 std::function<void()> unsubscribeCommonEventFunc = [wp, commonEventListener] () {
265 std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
266 if (innerCommonEventManager == nullptr) {
267 EVENT_LOGE("innerCommonEventManager not exist");
268 return;
269 }
270 bool ret = innerCommonEventManager->UnsubscribeCommonEvent(commonEventListener);
271 if (!ret) {
272 EVENT_LOGE("failed to unsubscribe event");
273 }
274 };
275
276 commonEventSrvQueue_->submit(unsubscribeCommonEventFunc);
277 return ERR_OK;
278 }
279
GetStickyCommonEvent(const std::string & event,CommonEventData & eventData)280 bool CommonEventManagerService::GetStickyCommonEvent(const std::string &event, CommonEventData &eventData)
281 {
282 EVENT_LOGD("enter");
283
284 if (!IsReady()) {
285 EVENT_LOGE("CommonEventManagerService not ready");
286 return false;
287 }
288
289 if (event.empty()) {
290 EVENT_LOGE("event is empty");
291 return false;
292 }
293
294 auto callingUid = IPCSkeleton::GetCallingUid();
295 std::string bundleName = DelayedSingleton<BundleManagerHelper>::GetInstance()->GetBundleName(callingUid);
296 const std::string permission = "ohos.permission.COMMONEVENT_STICKY";
297 bool ret = AccessTokenHelper::VerifyAccessToken(IPCSkeleton::GetCallingTokenID(), permission);
298 if (!ret) {
299 EVENT_LOGE("No permission to get a sticky common event from %{public}s (uid = %{public}d)",
300 bundleName.c_str(),
301 callingUid);
302 return false;
303 }
304
305 return innerCommonEventManager_->GetStickyCommonEvent(event, eventData);
306 }
307
DumpState(const uint8_t & dumpType,const std::string & event,const int32_t & userId,std::vector<std::string> & state)308 bool CommonEventManagerService::DumpState(const uint8_t &dumpType, const std::string &event, const int32_t &userId,
309 std::vector<std::string> &state)
310 {
311 EVENT_LOGD("enter");
312
313 auto callerToken = IPCSkeleton::GetCallingTokenID();
314 if (!AccessTokenHelper::VerifyShellToken(callerToken) && !AccessTokenHelper::VerifyNativeToken(callerToken)) {
315 EVENT_LOGE("Not subsystem or shell request");
316 return false;
317 }
318 if (!IsReady()) {
319 EVENT_LOGE("CommonEventManagerService not ready");
320 return false;
321 }
322
323 innerCommonEventManager_->DumpState(dumpType, event, userId, state);
324
325 return true;
326 }
327
FinishReceiver(const sptr<IRemoteObject> & proxy,const int32_t & code,const std::string & receiverData,const bool & abortEvent)328 bool CommonEventManagerService::FinishReceiver(
329 const sptr<IRemoteObject> &proxy, const int32_t &code, const std::string &receiverData, const bool &abortEvent)
330 {
331 EVENT_LOGD("enter");
332
333 if (!IsReady()) {
334 EVENT_LOGE("CommonEventManagerService not ready");
335 return false;
336 }
337 std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
338 std::function<void()> finishReceiverFunc = [wp, proxy, code, receiverData, abortEvent] () {
339 std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
340 if (innerCommonEventManager == nullptr) {
341 EVENT_LOGE("innerCommonEventManager not exist");
342 return;
343 }
344 innerCommonEventManager->FinishReceiver(proxy, code, receiverData, abortEvent);
345 };
346
347 commonEventSrvQueue_->submit(finishReceiverFunc);
348 return true;
349 }
350
Freeze(const uid_t & uid)351 bool CommonEventManagerService::Freeze(const uid_t &uid)
352 {
353 EVENT_LOGD("enter");
354
355 if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
356 EVENT_LOGE("Not subsystem request");
357 return false;
358 }
359 if (!IsReady()) {
360 EVENT_LOGE("CommonEventManagerService not ready");
361 return false;
362 }
363 std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
364 std::function<void()> freezeFunc = [wp, uid] () {
365 std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
366 if (innerCommonEventManager == nullptr) {
367 EVENT_LOGE("innerCommonEventManager not exist");
368 return;
369 }
370 innerCommonEventManager->Freeze(uid);
371 };
372
373 commonEventSrvQueue_->submit(freezeFunc);
374 return true;
375 }
376
Unfreeze(const uid_t & uid)377 bool CommonEventManagerService::Unfreeze(const uid_t &uid)
378 {
379 EVENT_LOGD("enter");
380
381 if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
382 EVENT_LOGE("Not subsystem request");
383 return false;
384 }
385 if (!IsReady()) {
386 EVENT_LOGE("CommonEventManagerService not ready");
387 return false;
388 }
389
390 std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
391 std::function<void()> unfreezeFunc = [wp, uid] () {
392 std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
393 if (innerCommonEventManager == nullptr) {
394 EVENT_LOGE("innerCommonEventManager not exist");
395 return;
396 }
397 innerCommonEventManager->Unfreeze(uid);
398 };
399
400 commonEventSrvQueue_->submit(unfreezeFunc);
401 return true;
402 }
403
UnfreezeAll()404 bool CommonEventManagerService::UnfreezeAll()
405 {
406 EVENT_LOGD("enter");
407
408 if (!AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID())) {
409 EVENT_LOGE("Not subsystem request");
410 return false;
411 }
412 if (!IsReady()) {
413 EVENT_LOGE("CommonEventManagerService not ready");
414 return false;
415 }
416
417 std::weak_ptr<InnerCommonEventManager> wp = innerCommonEventManager_;
418 std::function<void()> unfreezeAllFunc = [wp] () {
419 std::shared_ptr<InnerCommonEventManager> innerCommonEventManager = wp.lock();
420 if (innerCommonEventManager == nullptr) {
421 EVENT_LOGE("innerCommonEventManager not exist");
422 return;
423 }
424 innerCommonEventManager->UnfreezeAll();
425 };
426
427 commonEventSrvQueue_->submit(unfreezeAllFunc);
428 return true;
429 }
430
Dump(int fd,const std::vector<std::u16string> & args)431 int CommonEventManagerService::Dump(int fd, const std::vector<std::u16string> &args)
432 {
433 EVENT_LOGD("enter");
434
435 auto callerToken = IPCSkeleton::GetCallingTokenID();
436 if (!AccessTokenHelper::VerifyShellToken(callerToken) && !AccessTokenHelper::VerifyNativeToken(callerToken)) {
437 EVENT_LOGE("Not subsystem or shell request");
438 return ERR_NOTIFICATION_CES_COMMON_PERMISSION_DENIED;
439 }
440 if (!IsReady()) {
441 EVENT_LOGE("CommonEventManagerService not ready");
442 return ERR_INVALID_VALUE;
443 }
444 std::string result;
445 innerCommonEventManager_->HiDump(args, result);
446 int ret = dprintf(fd, "%s\n", result.c_str());
447 if (ret < 0) {
448 EVENT_LOGE("dprintf error");
449 return ERR_INVALID_VALUE;
450 }
451 return ERR_OK;
452 }
453
RemoveStickyCommonEvent(const std::string & event)454 int32_t CommonEventManagerService::RemoveStickyCommonEvent(const std::string &event)
455 {
456 EVENT_LOGI("enter");
457
458 if (!IsReady()) {
459 EVENT_LOGE("CommonEventManagerService not ready");
460 return ERR_NOTIFICATION_CESM_ERROR;
461 }
462
463 auto tokenId = IPCSkeleton::GetCallingTokenID();
464 bool isSubsystem = AccessTokenHelper::VerifyNativeToken(tokenId);
465 if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
466 EVENT_LOGE("Not system application or subsystem request.");
467 return ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP;
468 }
469
470 const std::string permission = "ohos.permission.COMMONEVENT_STICKY";
471 bool ret = AccessTokenHelper::VerifyAccessToken(tokenId, permission);
472 if (!ret && (!isSubsystem || supportCheckSaPermission_.compare("true") == 0)) {
473 EVENT_LOGE("No permission.");
474 return ERR_NOTIFICATION_CES_COMMON_PERMISSION_DENIED;
475 }
476
477 return innerCommonEventManager_->RemoveStickyCommonEvent(event, IPCSkeleton::GetCallingUid());
478 }
479
SetStaticSubscriberState(bool enable)480 int32_t CommonEventManagerService::SetStaticSubscriberState(bool enable)
481 {
482 if (!AccessTokenHelper::IsSystemApp()) {
483 EVENT_LOGE("Not system application");
484 return ERR_NOTIFICATION_CES_COMMON_NOT_SYSTEM_APP;
485 }
486
487 return innerCommonEventManager_->SetStaticSubscriberState(enable);
488 }
489 } // namespace EventFwk
490 } // namespace OHOS
491