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 "dlp_kv_data_storage.h"
17 #include <unistd.h>
18 #include "dlp_permission_log.h"
19 #include "dlp_permission.h"
20
21 namespace OHOS {
22 namespace Security {
23 namespace DlpPermission {
24 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpKvDataStorage"};
25 static const int32_t MAX_TIMES = 10;
26 static const int32_t SLEEP_INTERVAL = 100 * 1000;
27 static const std::string KV_STORE_EL1_BASE_DIR = "/data/service/el1/public/database/";
28 static const std::string KV_STORE_EL2_BASE_DIR = "/data/service/el2/public/database/";
29 static const std::string DLP_KV_APP_ID = "dlp_permission_service_storage";
30
DlpKvDataStorage(const std::string & storeId,const KvDataStorageOptions & options)31 DlpKvDataStorage::DlpKvDataStorage(const std::string &storeId,
32 const KvDataStorageOptions &options)
33 {
34 appId_.appId = DLP_KV_APP_ID;
35 storeId_.storeId = storeId;
36 options_ = options;
37 if (options_.area == DistributedKv::EL1) {
38 baseDir_ = KV_STORE_EL1_BASE_DIR + DLP_KV_APP_ID;
39 } else {
40 baseDir_ = KV_STORE_EL2_BASE_DIR + DLP_KV_APP_ID;
41 }
42 }
43
~DlpKvDataStorage()44 DlpKvDataStorage::~DlpKvDataStorage()
45 {
46 if (kvStorePtr_ != nullptr) {
47 dataManager_.CloseKvStore(appId_, kvStorePtr_);
48 }
49 }
50
TryTwice(const std::function<DistributedKv::Status ()> & func) const51 void DlpKvDataStorage::TryTwice(const std::function<DistributedKv::Status()> &func) const
52 {
53 OHOS::DistributedKv::Status status = func();
54 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
55 status = func();
56 DLP_LOG_ERROR(LABEL, "distribute database ipc error and try again, status = %{public}d", status);
57 }
58 }
59
LoadAllData(std::map<std::string,std::string> & infos)60 int32_t DlpKvDataStorage::LoadAllData(std::map<std::string, std::string> &infos)
61 {
62 bool res = CheckKvStore();
63 if (!res) {
64 DLP_LOG_ERROR(LABEL, "kvStore is nullptr");
65 return DLP_COMMON_CHECK_KVSTORE_ERROR;
66 }
67 OHOS::DistributedKv::Status status = DistributedKv::Status::SUCCESS;
68 std::vector<OHOS::DistributedKv::Entry> allEntries;
69 TryTwice([this, &status, &allEntries] {
70 status = GetEntries("", allEntries);
71 return status;
72 });
73 if (status != OHOS::DistributedKv::Status::SUCCESS) {
74 DLP_LOG_ERROR(LABEL, "get entries error: %{public}d", status);
75 return DLP_QUERY_DISTRIBUTE_DATA_ERROR;
76 }
77 infos.clear();
78 SaveEntries(allEntries, infos);
79 return ERR_OK;
80 }
81
GetKvStore()82 OHOS::DistributedKv::Status DlpKvDataStorage::GetKvStore()
83 {
84 OHOS::DistributedKv::Options options = {
85 .createIfMissing = true,
86 .encrypt = false,
87 .autoSync = options_.autoSync,
88 .syncable = options_.autoSync,
89 .securityLevel = options_.securityLevel,
90 .area = options_.area,
91 .kvStoreType = OHOS::DistributedKv::KvStoreType::SINGLE_VERSION,
92 .baseDir = baseDir_,
93 };
94 OHOS::DistributedKv::Status status = dataManager_.GetSingleKvStore(options, appId_, storeId_, kvStorePtr_);
95 bool res = (status != OHOS::DistributedKv::Status::SUCCESS) || (kvStorePtr_ == nullptr);
96 if (res) {
97 DLP_LOG_ERROR(LABEL, "GetSingleKvStore failed! status %{public}d, kvStorePtr_ is nullptr", status);
98 }
99 return status;
100 }
101
CheckKvStore()102 bool DlpKvDataStorage::CheckKvStore()
103 {
104 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
105 if (kvStorePtr_ != nullptr) {
106 return true;
107 }
108 int32_t tryTimes = MAX_TIMES;
109 OHOS::DistributedKv::Status status = OHOS::DistributedKv::Status::SUCCESS;
110 while (tryTimes > 0) {
111 status = GetKvStore();
112 bool res = (status == OHOS::DistributedKv::Status::SUCCESS) && (kvStorePtr_ != nullptr);
113 if (res) {
114 return true;
115 }
116 usleep(SLEEP_INTERVAL);
117 tryTimes--;
118 }
119 return false;
120 }
121
AddOrUpdateValue(const std::string & key,const std::string & value)122 int32_t DlpKvDataStorage::AddOrUpdateValue(const std::string &key, const std::string &value)
123 {
124 if (key.empty() || value.empty()) {
125 DLP_LOG_ERROR(LABEL, "param is empty!");
126 return DLP_KV_DATE_INFO_EMPTY_ERROR;
127 }
128 return PutValueToKvStore(key, value);
129 }
130
RemoveValueFromKvStore(const std::string & keyStr)131 int32_t DlpKvDataStorage::RemoveValueFromKvStore(const std::string &keyStr)
132 {
133 if (!CheckKvStore()) {
134 DLP_LOG_ERROR(LABEL, "kvStore is nullptr");
135 return DLP_COMMON_CHECK_KVSTORE_ERROR;
136 }
137 OHOS::DistributedKv::Key key(keyStr);
138 OHOS::DistributedKv::Status status;
139 OHOS::DistributedKv::Value value;
140 {
141 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
142 // check exist
143 status = kvStorePtr_->Get(key, value);
144 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
145 DLP_LOG_ERROR(LABEL, "kvstore ipc error and try again, status = %{public}d", status);
146 status = kvStorePtr_->Get(key, value);
147 }
148 if (status != OHOS::DistributedKv::Status::SUCCESS) {
149 DLP_LOG_INFO(LABEL, "key does not exist in kvStore.");
150 return DLP_OK;
151 }
152 // delete
153 status = kvStorePtr_->Delete(key);
154 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
155 status = kvStorePtr_->Delete(key);
156 DLP_LOG_ERROR(LABEL, "kvstore ipc error and try to call again, status = %{public}d", status);
157 }
158 }
159 if (status != OHOS::DistributedKv::Status::SUCCESS) {
160 DLP_LOG_ERROR(LABEL, "delete key from kvstore failed, status %{public}d.", status);
161 return DLP_COMMON_DELETE_KEY_FROM_KVSTORE_ERROR;
162 }
163 DLP_LOG_DEBUG(LABEL, "delete key from kvStore succeed!");
164 return DLP_OK;
165 }
166
DeleteKvStore()167 int32_t DlpKvDataStorage::DeleteKvStore()
168 {
169 bool res = CheckKvStore();
170 if (!res) {
171 DLP_LOG_ERROR(LABEL, "kvStore is nullptr");
172 return DLP_QUERY_DISTRIBUTE_DATA_ERROR;
173 }
174 OHOS::DistributedKv::Status status;
175 {
176 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
177 dataManager_.CloseKvStore(this->appId_, this->storeId_);
178 kvStorePtr_ = nullptr;
179 status = dataManager_.DeleteKvStore(this->appId_, this->storeId_, baseDir_);
180 }
181 if (status != OHOS::DistributedKv::Status::SUCCESS) {
182 DLP_LOG_ERROR(LABEL, "error, status = %{public}d", status);
183 return DLP_QUERY_DISTRIBUTE_DATA_ERROR;
184 }
185 return DLP_OK;
186 }
187
PutValueToKvStore(const std::string & keyStr,const std::string & valueStr)188 int32_t DlpKvDataStorage::PutValueToKvStore(const std::string &keyStr, const std::string &valueStr)
189 {
190 bool res = CheckKvStore();
191 if (!res) {
192 DLP_LOG_ERROR(LABEL, "kvStore is nullptr");
193 return DLP_COMMON_CHECK_KVSTORE_ERROR;
194 }
195 OHOS::DistributedKv::Key key(keyStr);
196 OHOS::DistributedKv::Value value(valueStr);
197 OHOS::DistributedKv::Status status;
198 {
199 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
200 status = kvStorePtr_->Put(key, value);
201 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
202 status = kvStorePtr_->Put(key, value);
203 }
204 }
205 if (status != OHOS::DistributedKv::Status::SUCCESS) {
206 DLP_LOG_ERROR(LABEL, "put value to kvStore error, status = %{public}d", status);
207 return DLP_QUERY_DISTRIBUTE_DATA_ERROR;
208 }
209 return DLP_OK;
210 }
211
GetValueFromKvStore(const std::string & keyStr,std::string & valueStr)212 int32_t DlpKvDataStorage::GetValueFromKvStore(const std::string &keyStr, std::string &valueStr)
213 {
214 bool res = CheckKvStore();
215 if (!res) {
216 DLP_LOG_ERROR(LABEL, "kvStore is nullptr");
217 return DLP_COMMON_CHECK_KVSTORE_ERROR;
218 }
219 OHOS::DistributedKv::Key key(keyStr);
220 OHOS::DistributedKv::Value value;
221 OHOS::DistributedKv::Status status;
222 {
223 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
224 status = kvStorePtr_->Get(key, value);
225 if (status == OHOS::DistributedKv::Status::IPC_ERROR) {
226 DLP_LOG_ERROR(LABEL, "kvstore ipc error and try again, status = %{public}d", status);
227 status = kvStorePtr_->Get(key, value);
228 }
229 }
230 if (status != OHOS::DistributedKv::Status::SUCCESS) {
231 DLP_LOG_ERROR(LABEL, "get value from kvstore error, status %{public}d.", status);
232 return DLP_QUERY_DISTRIBUTE_DATA_ERROR;
233 }
234 valueStr = value.ToString();
235 return DLP_OK;
236 }
237
GetEntries(std::string subId,std::vector<OHOS::DistributedKv::Entry> & allEntries) const238 OHOS::DistributedKv::Status DlpKvDataStorage::GetEntries(
239 std::string subId, std::vector<OHOS::DistributedKv::Entry> &allEntries) const
240 {
241 OHOS::DistributedKv::Key allEntryKeyPrefix(subId);
242 std::lock_guard<std::mutex> lock(kvStorePtrMutex_);
243 OHOS::DistributedKv::Status status = kvStorePtr_->GetEntries(allEntryKeyPrefix, allEntries);
244 return status;
245 }
246
IsKeyExists(const std::string & keyStr)247 bool DlpKvDataStorage::IsKeyExists(const std::string &keyStr)
248 {
249 if (keyStr.empty()) {
250 DLP_LOG_ERROR(LABEL, "param is empty!");
251 return false;
252 }
253 std::string valueStr;
254 return GetValueFromKvStore(keyStr, valueStr) == DLP_OK;
255 }
256 } // namespace DlpPermission
257 } // namespace Security
258 } // namespace OHOS
259