1 /*
2 * Copyright (C) 2022 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 "permission_utils.h"
16
17 #include <unordered_set>
18
19 #include "accesstoken_kit.h"
20 #include "ipc_skeleton.h"
21 #include "media_log.h"
22 #include "medialibrary_tracer.h"
23 #include "privacy_kit.h"
24 #include "iservice_registry.h"
25 #include "system_ability_definition.h"
26
27 namespace OHOS {
28 namespace Media {
29 using namespace std;
30 using namespace OHOS::Security::AccessToken;
31 using namespace OHOS::AppExecFwk::Constants;
32
33 sptr<AppExecFwk::IBundleMgr> PermissionUtils::bundleMgr_ = nullptr;
34 mutex PermissionUtils::bundleMgrMutex_;
35
GetSysBundleManager()36 sptr<AppExecFwk::IBundleMgr> PermissionUtils::GetSysBundleManager()
37 {
38 if (bundleMgr_ != nullptr) {
39 return bundleMgr_;
40 }
41
42 lock_guard<mutex> lock(bundleMgrMutex_);
43 if (bundleMgr_ != nullptr) {
44 return bundleMgr_;
45 }
46
47 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
48 if (systemAbilityMgr == nullptr) {
49 MEDIA_ERR_LOG("Failed to get SystemAbilityManager.");
50 return nullptr;
51 }
52
53 auto bundleObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
54 if (bundleObj == nullptr) {
55 MEDIA_ERR_LOG("Remote object is nullptr.");
56 return nullptr;
57 }
58
59 auto bundleMgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
60 if (bundleMgr == nullptr) {
61 MEDIA_ERR_LOG("Failed to iface_cast");
62 return nullptr;
63 }
64 bundleMgr_ = bundleMgr;
65
66 return bundleMgr_;
67 }
68
GetClientBundle(const int uid,string & bundleName,bool & isSystemApp)69 void PermissionUtils::GetClientBundle(const int uid, string &bundleName, bool &isSystemApp)
70 {
71 bundleMgr_ = GetSysBundleManager();
72 if (bundleMgr_ == nullptr) {
73 bundleName = "";
74 isSystemApp = false;
75 return;
76 }
77 auto result = bundleMgr_->GetBundleNameForUid(uid, bundleName);
78 if (!result) {
79 MEDIA_ERR_LOG("GetBundleNameForUid fail");
80 bundleName = "";
81 }
82 isSystemApp = bundleMgr_->CheckIsSystemAppByUid(uid);
83 }
84
85 #ifdef OHOS_DEBUG
ShouldAddPermissionRecord(const AccessTokenID & token)86 bool inline ShouldAddPermissionRecord(const AccessTokenID &token)
87 {
88 return (AccessTokenKit::GetTokenTypeFlag(token) == TOKEN_HAP);
89 }
90
AddPermissionRecord(const AccessTokenID & token,const string & perm,const bool permGranted)91 void AddPermissionRecord(const AccessTokenID &token, const string &perm, const bool permGranted)
92 {
93 if (!ShouldAddPermissionRecord(token)) {
94 return;
95 }
96
97 int res = PrivacyKit::AddPermissionUsedRecord(token, perm, !!permGranted, !permGranted);
98 if (res != 0) {
99 /* Failed to add permission used record, not fatal */
100 MEDIA_WARN_LOG("Failed to add permission used record: %{public}s, permGranted: %{public}d, err: %{public}d",
101 perm.c_str(), permGranted, res);
102 }
103 }
104 #endif
105
CheckCallerPermission(const string & permission)106 bool PermissionUtils::CheckCallerPermission(const string &permission)
107 {
108 MediaLibraryTracer tracer;
109 tracer.Start("CheckCallerPermission");
110
111 AccessTokenID tokenCaller = IPCSkeleton::GetCallingTokenID();
112 int res = AccessTokenKit::VerifyAccessToken(tokenCaller, permission);
113 if (res != PermissionState::PERMISSION_GRANTED) {
114 MEDIA_ERR_LOG("MediaLibraryDataManager Query: Have no media permission: %{public}s", permission.c_str());
115 #ifdef OHOS_DEBUG
116 AddPermissionRecord(tokenCaller, permission, false);
117 #endif
118 return false;
119 }
120 #ifdef OHOS_DEBUG
121 AddPermissionRecord(tokenCaller, permission, true);
122 #endif
123
124 return true;
125 }
126
CheckCallerPermission(const std::array<std::string,PERM_GRP_SIZE> & perms,const uint32_t typeMask)127 bool PermissionUtils::CheckCallerPermission(const std::array<std::string, PERM_GRP_SIZE> &perms,
128 const uint32_t typeMask)
129 {
130 MediaLibraryTracer tracer;
131 tracer.Start("CheckCallerPermissionWithTypeMask");
132
133 if (typeMask == 0) {
134 return false;
135 }
136
137 uint32_t resultMask = 0;
138 for (auto &perm : perms) {
139 uint32_t bit = static_cast<uint32_t>(PERM_MASK_MAP.at(perm));
140 if ((bit & typeMask)) {
141 if (PermissionUtils::CheckCallerPermission(perm)) {
142 resultMask |= bit;
143 } else {
144 return false;
145 }
146 }
147 }
148 /*
149 * Grant if all non-zero bit in typeMask passed permission check,
150 * in that case, resultMask should be the same with typeMask
151 */
152 if (resultMask == typeMask) {
153 return true;
154 }
155
156 return false;
157 }
158 } // namespace Media
159 } // namespace OHOS
160