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
16 #include "uri_permission_rdb.h"
17
18 #include <string>
19 #include <vector>
20
21 #include "scope_guard.h"
22 #include "ability_manager_errors.h"
23 #include "hilog_wrapper.h"
24 #include "want.h"
25
26 namespace OHOS {
27 namespace AAFwk {
28
29 namespace {
30 const std::string URI_PERMISSION_RDB_NAME = "/uripmdb.db";
31 const std::string URI_PERMISSION_TABLE_NAME = "uri_permission";
32 const std::string COLUMN_URI = "URI";
33 const std::string COLUMN_FLAG = "FLAG";
34 const std::string COLUMN_FROM_TOKEN_ID = "FROM_TOKEN_ID";
35 const std::string COLUMN_TARGET_TOKEN_ID = "TARGET_TOKEN_ID";
36 const int32_t COLUMN_URI_INDEX = 1;
37 const int32_t COLUMN_FLAG_INDEX = 2;
38 const int32_t COLUMN_FROM_TOKEN_ID_INDEX = 3;
39 const int32_t COLUMN_TARGET_TOKEN_ID_INDEX = 4;
40 }
41
PrintRdbGrantInfo(const RdbGrantInfo & info)42 void PrintRdbGrantInfo(const RdbGrantInfo &info)
43 {
44 HILOG_DEBUG("uri: %{private}s, flag: %{public}u, fromTokenId: %{public}u, targetTokenId: %{public}u.",
45 info.uri.c_str(), info.flag, info.fromTokenId, info.targetTokenId);
46 }
47
UriPermissionRdb()48 UriPermissionRdb::UriPermissionRdb()
49 {
50 HILOG_DEBUG("UriPermissionRdb: Create DataBase");
51 RdbConfig rdbConfig;
52 rdbConfig.dbName = URI_PERMISSION_RDB_NAME;
53 rdbConfig.tableName = URI_PERMISSION_TABLE_NAME;
54 // create database
55 rdbConfig.createTableSql = std::string("CREATE TABLE IF NOT EXISTS " + URI_PERMISSION_TABLE_NAME +
56 "(ID INTEGER PRIMARY KEY AUTOINCREMENT, URI TEXT NOT NULL, " +
57 "FLAG INTEGER, FROM_TOKEN_ID INTEGER, TARGET_TOKEN_ID INTEGER);");
58 HILOG_DEBUG("CreateTableSql: %{public}s", rdbConfig.createTableSql.c_str());
59 rdbDataManager_ = std::make_shared<RdbDataManager>(rdbConfig);
60 bool ret = rdbDataManager_->CreateTable();
61 if (!ret) {
62 HILOG_ERROR("Failed to createTable");
63 }
64 }
65
AddGrantInfo(const std::string & uri,uint32_t flag,uint32_t fromTokenId,uint32_t targetTokenId)66 int32_t UriPermissionRdb::AddGrantInfo(const std::string &uri, uint32_t flag, uint32_t fromTokenId,
67 uint32_t targetTokenId)
68 {
69 HILOG_INFO("AddGrantInfo uri=%{private}s, flag=%{public}u, fromTokenId=%{public}u, targetTokenId=%{public}u.",
70 uri.c_str(), flag, fromTokenId, targetTokenId);
71 NativeRdb::AbsRdbPredicates absRdbPredicates(URI_PERMISSION_TABLE_NAME);
72 absRdbPredicates.EqualTo(COLUMN_FROM_TOKEN_ID, std::to_string(fromTokenId));
73 absRdbPredicates.EqualTo(COLUMN_TARGET_TOKEN_ID, std::to_string(targetTokenId));
74 absRdbPredicates.EqualTo(COLUMN_URI, uri);
75 std::vector<RdbGrantInfo> rdbGrantInfoList;
76 int rowCount;
77 bool ret = QueryData(absRdbPredicates, rdbGrantInfoList, rowCount);
78 if (!ret) {
79 HILOG_ERROR("QueryData failed");
80 return INNER_ERR;
81 }
82 HILOG_DEBUG("rowCount = %{public}d", rowCount);
83 // should query no more than one uri permission
84 if (rowCount > 1) {
85 HILOG_ERROR("Query more than one uri permission grant info!");
86 for (const auto &info : rdbGrantInfoList) {
87 PrintRdbGrantInfo(info);
88 }
89 return INNER_ERR;
90 }
91 if (rowCount == 0) {
92 HILOG_INFO("Add a new uri permission info");
93 RdbGrantInfo grantInfo = { uri, flag, static_cast<uint32_t>(fromTokenId),
94 static_cast<uint32_t>(targetTokenId) };
95 rdbGrantInfoList.push_back(grantInfo);
96 ret = InsertData(rdbGrantInfoList);
97 if (!ret) {
98 HILOG_ERROR("InsertData failed");
99 return INNER_ERR;
100 }
101 return ERR_OK;
102 }
103 // update flag
104 if ((rdbGrantInfoList[0].flag & flag) == Want::FLAG_AUTH_PERSISTABLE_URI_PERMISSION) {
105 HILOG_INFO("Update an uri permission info");
106 NativeRdb::ValuesBucket valuesBucket;
107 valuesBucket.PutInt(COLUMN_FLAG, flag);
108 ret = UpdateData(absRdbPredicates, valuesBucket);
109 if (!ret) {
110 HILOG_ERROR("UpdateData failed");
111 return INNER_ERR;
112 }
113 return ERR_OK;
114 }
115 HILOG_INFO("Uri has been granted");
116 return ERR_OK;
117 }
118
RemoveGrantInfo(uint32_t tokenId,sptr<StorageManager::IStorageManager> storageManager)119 int32_t UriPermissionRdb::RemoveGrantInfo(uint32_t tokenId, sptr<StorageManager::IStorageManager> storageManager)
120 {
121 HILOG_INFO("RemoveGrantInfo, TokenId = %{public}u", tokenId);
122 NativeRdb::AbsRdbPredicates absRdbPredicates(URI_PERMISSION_TABLE_NAME);
123 absRdbPredicates.EqualTo(COLUMN_FROM_TOKEN_ID, std::to_string(tokenId));
124 absRdbPredicates.Or();
125 absRdbPredicates.EqualTo(COLUMN_TARGET_TOKEN_ID, std::to_string(tokenId));
126 int ret = RemoveGrantInfo(absRdbPredicates, storageManager);
127 return ret;
128 }
129
RemoveGrantInfo(const std::string & uri,uint32_t tokenId,sptr<StorageManager::IStorageManager> storageManager)130 int32_t UriPermissionRdb::RemoveGrantInfo(const std::string &uri, uint32_t tokenId,
131 sptr<StorageManager::IStorageManager> storageManager)
132 {
133 HILOG_INFO("RemoveGrantInfo, uri = %{private}s, TokenId = %{public}u", uri.c_str(), tokenId);
134 NativeRdb::AbsRdbPredicates absRdbPredicates(URI_PERMISSION_TABLE_NAME);
135 absRdbPredicates.EqualTo(COLUMN_URI, uri);
136 absRdbPredicates.EqualTo(COLUMN_TARGET_TOKEN_ID, std::to_string(tokenId));
137 int ret = RemoveGrantInfo(absRdbPredicates, storageManager);
138 return ret;
139 }
140
RemoveGrantInfo(const NativeRdb::AbsRdbPredicates & absRdbPredicates,sptr<StorageManager::IStorageManager> storageManager)141 int32_t UriPermissionRdb::RemoveGrantInfo(const NativeRdb::AbsRdbPredicates &absRdbPredicates,
142 sptr<StorageManager::IStorageManager> storageManager)
143 {
144 if (storageManager == nullptr) {
145 HILOG_ERROR("storageManager is nullptr!");
146 return INNER_ERR;
147 }
148 std::map<unsigned int, std::vector<std::string>> uriLists;
149 int rowCount;
150 std::vector<RdbGrantInfo> rdbGrantInfoList;
151 bool ret = QueryData(absRdbPredicates, rdbGrantInfoList, rowCount);
152 if (!ret) {
153 return INNER_ERR;
154 }
155 for (const auto &info : rdbGrantInfoList) {
156 uriLists[info.targetTokenId].emplace_back(info.uri);
157 }
158 // 1. delete share file
159 for (auto iter = uriLists.begin(); iter != uriLists.end(); iter++) {
160 storageManager->DeleteShareFile(iter->first, iter->second);
161 }
162 // 2. delete rdb data
163 HILOG_DEBUG("total %{public}u uri permissions info to be removed", rowCount);
164 ret = DeleteData(absRdbPredicates);
165 if (!ret) {
166 HILOG_ERROR("RemoveGrantInfo failed");
167 return INNER_ERR;
168 }
169 return ERR_OK;
170 }
171
CheckPersistableUriPermissionProxy(const std::string & uri,uint32_t flag,uint32_t tokenId)172 bool UriPermissionRdb::CheckPersistableUriPermissionProxy(const std::string& uri, uint32_t flag, uint32_t tokenId)
173 {
174 // check if the uri has flag permission
175 HILOG_DEBUG(
176 "CheckPersistablekUriPermissionProxy: uri = %{private}s, flag = %{public}i, tokenId = %{public}i",
177 uri.c_str(), flag, tokenId);
178 NativeRdb::AbsRdbPredicates absRdbPredicates(URI_PERMISSION_TABLE_NAME);
179 absRdbPredicates.EqualTo(COLUMN_URI, uri);
180 absRdbPredicates.EqualTo(COLUMN_TARGET_TOKEN_ID, std::to_string(tokenId));
181 int rowCount;
182 std::vector<RdbGrantInfo> rdbGrantInfoList;
183 bool ret = QueryData(absRdbPredicates, rdbGrantInfoList, rowCount);
184 flag &= (~Want::FLAG_AUTH_PERSISTABLE_URI_PERMISSION);
185 if (ret && rowCount > 0) {
186 for (const auto &info : rdbGrantInfoList) {
187 if (((info.flag | Want::FLAG_AUTH_READ_URI_PERMISSION) & flag) != 0) {
188 HILOG_DEBUG("CheckUriPermissionProxy ok.");
189 return true;
190 }
191 }
192 }
193 HILOG_DEBUG("CheckUriPermissionProxy failed.");
194 return false;
195 }
196
ShowAllGrantInfo()197 void UriPermissionRdb::ShowAllGrantInfo()
198 {
199 NativeRdb::AbsRdbPredicates absRdbPredicates(URI_PERMISSION_TABLE_NAME);
200 std::vector<RdbGrantInfo> rdbGrantInfoList;
201 int rowCount;
202 bool ret = QueryData(absRdbPredicates, rdbGrantInfoList, rowCount);
203 if (!ret) {
204 HILOG_WARN("failed to query");
205 }
206 }
207
GetGrantInfo(std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet,std::vector<RdbGrantInfo> & rdbGrantInfoList)208 bool UriPermissionRdb::GetGrantInfo(std::shared_ptr<NativeRdb::AbsSharedResultSet> absSharedResultSet,
209 std::vector<RdbGrantInfo> &rdbGrantInfoList)
210 {
211 if (absSharedResultSet == nullptr) {
212 return false;
213 }
214 std::string uri;
215 bool ret = absSharedResultSet->GetString(COLUMN_URI_INDEX, uri);
216 if (ret != NativeRdb::E_OK) {
217 HILOG_ERROR("Get COLUMN_URI_INDEX failed");
218 return false;
219 }
220 int flag;
221 ret = absSharedResultSet->GetInt(COLUMN_FLAG_INDEX, flag);
222 if (ret != NativeRdb::E_OK) {
223 HILOG_ERROR("Get COLUMN_TARGET_TOKEN_ID_INDEX failed");
224 return false;
225 }
226 int targetTokenId;
227 ret = absSharedResultSet->GetInt(COLUMN_TARGET_TOKEN_ID_INDEX, targetTokenId);
228 if (ret != NativeRdb::E_OK) {
229 HILOG_ERROR("Get COLUMN_FLAG_INDEX failed");
230 return false;
231 }
232 int fromTokenId;
233 ret = absSharedResultSet->GetInt(COLUMN_FROM_TOKEN_ID_INDEX, fromTokenId);
234 if (ret != NativeRdb::E_OK) {
235 HILOG_ERROR("Get COLUMN_FROM_TOKEN_ID_INDEX failed");
236 return false;
237 }
238 RdbGrantInfo grantInfo = { uri, flag, static_cast<uint32_t>(fromTokenId), static_cast<uint32_t>(targetTokenId) };
239 rdbGrantInfoList.push_back(grantInfo);
240 return true;
241 }
242
QueryData(const NativeRdb::AbsRdbPredicates & absRdbPredicates,std::vector<RdbGrantInfo> & rdbGrantInfoList,int & rowCount)243 bool UriPermissionRdb::QueryData(const NativeRdb::AbsRdbPredicates &absRdbPredicates,
244 std::vector<RdbGrantInfo> &rdbGrantInfoList, int &rowCount)
245 {
246 auto absSharedResultSet = rdbDataManager_->QueryData(absRdbPredicates);
247 if (absSharedResultSet == nullptr) {
248 HILOG_ERROR("UriPermissionRdb::QueryData failed");
249 return false;
250 }
251 ScopeGuard stateGuard([&] { absSharedResultSet->Close(); });
252 int ret = absSharedResultSet->GetRowCount(rowCount);
253 if (ret != NativeRdb::E_OK) {
254 HILOG_ERROR("GetRowCount failed");
255 return false;
256 }
257 if (rowCount == 0) {
258 HILOG_DEBUG("Query Result, total %{public}i uri", rowCount);
259 return true;
260 }
261 ret = absSharedResultSet->GoToFirstRow();
262 if (ret != NativeRdb::E_OK) {
263 HILOG_ERROR("GoToFirstRow failed");
264 return false;
265 }
266 do {
267 // ger grant info from query result
268 bool result = GetGrantInfo(absSharedResultSet, rdbGrantInfoList);
269 if (!result) {
270 return false;
271 }
272 } while (absSharedResultSet->GoToNextRow() == NativeRdb::E_OK);
273 HILOG_DEBUG("Query Result, total %{public}i uri", rowCount);
274 for (const auto &info : rdbGrantInfoList) {
275 PrintRdbGrantInfo(info);
276 }
277 return true;
278 }
279
InsertData(const std::vector<RdbGrantInfo> & rdbGrantInfoList)280 bool UriPermissionRdb::InsertData(const std::vector<RdbGrantInfo> &rdbGrantInfoList)
281 {
282 std::vector<NativeRdb::ValuesBucket> valuesBuckets;
283 int64_t grantInfoNum = static_cast<int64_t>(rdbGrantInfoList.size());
284 for (int i = 0; i < grantInfoNum; i++) {
285 NativeRdb::ValuesBucket valuesBucket;
286 valuesBucket.PutString(COLUMN_URI, rdbGrantInfoList[i].uri);
287 valuesBucket.PutInt(COLUMN_FLAG, rdbGrantInfoList[i].flag);
288 valuesBucket.PutInt(COLUMN_FROM_TOKEN_ID, rdbGrantInfoList[i].fromTokenId);
289 valuesBucket.PutInt(COLUMN_TARGET_TOKEN_ID, rdbGrantInfoList[i].targetTokenId);
290 valuesBuckets.push_back(valuesBucket);
291 }
292 bool ret = rdbDataManager_->BatchInsert(grantInfoNum, valuesBuckets);
293 return ret;
294 }
295
UpdateData(const NativeRdb::AbsRdbPredicates & absRdbPredicates,const NativeRdb::ValuesBucket & valuesBucket)296 bool UriPermissionRdb::UpdateData(const NativeRdb::AbsRdbPredicates &absRdbPredicates,
297 const NativeRdb::ValuesBucket &valuesBucket)
298 {
299 bool ret = rdbDataManager_->UpdateData(valuesBucket, absRdbPredicates);
300 return ret;
301 }
302
DeleteData(const NativeRdb::AbsRdbPredicates & absRdbPredicates)303 bool UriPermissionRdb::DeleteData(const NativeRdb::AbsRdbPredicates &absRdbPredicates)
304 {
305 bool ret = rdbDataManager_->DeleteData(absRdbPredicates);
306 return ret;
307 }
308 }
309 }
310