1 /*
2 * Copyright (c) 2024 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 #define LOG_TAG "RdConnection"
16 #include "rd_connection.h"
17
18 #include <securec.h>
19 #include <string>
20
21 #include "logger.h"
22 #include "grd_api_manager.h"
23 #include "rd_statement.h"
24 #include "rdb_errno.h"
25 #include "rdb_security_manager.h"
26 #include "sqlite_global_config.h"
27 #include "sqlite_utils.h"
28
29 namespace OHOS {
30 namespace NativeRdb {
31 using namespace OHOS::Rdb;
32 __attribute__((used))
33 const int32_t RdConnection::regCreator_ = Connection::RegisterCreator(DB_VECTOR, RdConnection::Create);
34 __attribute__((used))
35 const int32_t RdConnection::regRepairer_ = Connection::RegisterRepairer(DB_VECTOR, RdConnection::Repair);
36 __attribute__((used))
37 const int32_t RdConnection::regDeleter_ = Connection::RegisterDeleter(DB_VECTOR, RdConnection::Delete);
38
Create(const RdbStoreConfig& config, bool isWrite)39 std::pair<int32_t, std::shared_ptr<Connection>> RdConnection::Create(const RdbStoreConfig& config, bool isWrite)
40 {
41 std::pair<int32_t, std::shared_ptr<Connection>> result = { E_ERROR, nullptr };
42 if (!IsUsingArkData() || config.GetStorageMode() == StorageMode::MODE_MEMORY) {
43 result.first = E_NOT_SUPPORT;
44 return result;
45 }
46 auto& [errCode, conn] = result;
47 for (size_t i = 0; i < ITERS_COUNT; i++) {
48 std::shared_ptr<RdConnection> connection = std::make_shared<RdConnection>(config, isWrite);
49 if (connection == nullptr) {
50 LOG_ERROR("SqliteConnection::Open new failed, connection is nullptr.");
51 return result;
52 }
53 errCode = connection->InnerOpen(config);
54 if (errCode == E_OK) {
55 conn = connection;
56 break;
57 }
58 }
59 return result;
60 }
61
Repair(const RdbStoreConfig& config)62 int32_t RdConnection::Repair(const RdbStoreConfig& config)
63 {
64 std::string dbPath = "";
65 auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
66 if (errCode != E_OK) {
67 LOG_ERROR("Can not get db path.");
68 return errCode;
69 }
70 std::vector<uint8_t> key = config.GetEncryptKey();
71 errCode = RdUtils::RdDbRepair(dbPath.c_str(), GetConfigStr(key, config.IsEncrypt()).c_str());
72 key.assign(key.size(), 0);
73 if (errCode != E_OK) {
74 LOG_ERROR("Fail to repair db.");
75 }
76 return errCode;
77 }
78
79 static constexpr const char *RD_POST_FIXES[] = {
80 "",
81 ".redo",
82 ".undo",
83 ".ctrl",
84 ".ctrl.dwr",
85 ".safe",
86 ".map",
87 ".corruptedflg",
88 };
89
Delete(const RdbStoreConfig &config)90 int32_t RdConnection::Delete(const RdbStoreConfig &config)
91 {
92 auto path = config.GetPath();
93 for (auto postFix : RD_POST_FIXES) {
94 std::string shmFilePath = path + postFix;
95 if (access(shmFilePath.c_str(), F_OK) == 0) {
96 remove(shmFilePath.c_str());
97 }
98 }
99 return E_OK;
100 }
101
RdConnection(const RdbStoreConfig &config, bool isWriter)102 RdConnection::RdConnection(const RdbStoreConfig &config, bool isWriter) : isWriter_(isWriter), config_(config)
103 {
104 }
105
~RdConnection()106 RdConnection::~RdConnection()
107 {
108 if (dbHandle_ != nullptr) {
109 int errCode = RdUtils::RdDbClose(dbHandle_, 0);
110 if (errCode != E_OK) {
111 LOG_ERROR("~RdConnection ~RdConnection: could not close database err = %{public}d", errCode);
112 }
113 dbHandle_ = nullptr;
114 }
115 }
116
GetConfigStr(const std::vector<uint8_t> &keys, bool isEncrypt)117 std::string RdConnection::GetConfigStr(const std::vector<uint8_t> &keys, bool isEncrypt)
118 {
119 std::string config = "{";
120 if (isEncrypt) {
121 const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '/0'
122 char keyBuff[keyBuffSize];
123 config += "\"isEncrypted\":1,";
124 config += "\"hexPassword\":\"";
125 config += RdUtils::GetEncryptKey(keys, keyBuff, keyBuffSize);
126 config += "\",";
127 (void)memset_s(keyBuff, keyBuffSize, 0, keyBuffSize);
128 }
129 config += RdConnection::GRD_OPEN_CONFIG_STR;
130 config += "}";
131 return config;
132 }
133
134
InnerOpen(const RdbStoreConfig &config)135 int RdConnection::InnerOpen(const RdbStoreConfig &config)
136 {
137 std::string dbPath = "";
138 auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
139 if (errCode != E_OK) {
140 LOG_ERROR("Can not get db path.");
141 return errCode;
142 }
143 std::vector<uint8_t> newKey = config.GetNewEncryptKey();
144 if (!newKey.empty()) {
145 newKey.assign(newKey.size(), 0);
146 errCode = ReSetKey(config);
147 if (errCode != E_OK) {
148 LOG_ERROR("Can not reset key %{public}d.", errCode);
149 return errCode;
150 }
151 }
152
153 std::vector<uint8_t> key = config.GetEncryptKey();
154 std::string configStr = GetConfigStr(key, config.IsEncrypt());
155 errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_);
156 if (errCode == E_CHANGE_UNENCRYPTED_TO_ENCRYPTED) {
157 errCode = RdUtils::RdDbRekey(dbPath.c_str(), GetConfigStr({}, false).c_str(), key);
158 if (errCode != E_OK) {
159 key.assign(key.size(), 0);
160 RdUtils::ClearAndZeroString(configStr);
161 LOG_ERROR("Can not rekey caylay db %{public}d.", errCode);
162 return errCode;
163 }
164 errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_);
165 }
166 key.assign(key.size(), 0);
167 RdUtils::ClearAndZeroString(configStr);
168 if (errCode != E_OK) {
169 LOG_ERROR("Can not open rd db %{public}d.", errCode);
170 return errCode;
171 }
172 return errCode;
173 }
174
OnInitialize()175 int32_t RdConnection::OnInitialize()
176 {
177 return E_NOT_SUPPORT;
178 }
179
CreateStatement(const std::string& sql, Connection::SConn conn)180 std::pair<int32_t, RdConnection::Stmt> RdConnection::CreateStatement(const std::string& sql, Connection::SConn conn)
181 {
182 auto stmt = std::make_shared<RdStatement>();
183 stmt->conn_ = conn;
184 stmt->config_ = &config_;
185 stmt->setPragmas_["user_version"] = ([this](const int &value) -> int32_t {
186 return RdUtils::RdDbSetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, value);
187 });
188 stmt->getPragmas_["user_version"] = ([this](int &version) -> int32_t {
189 return RdUtils::RdDbGetVersion(dbHandle_, GRD_CONFIG_USER_VERSION, version);
190 });
191 int32_t ret = stmt->Prepare(dbHandle_, sql);
192 if (ret != E_OK) {
193 return { ret, nullptr };
194 }
195 return { ret, stmt };
196 }
197
GetDBType() const198 int32_t RdConnection::GetDBType() const
199 {
200 return DB_VECTOR;
201 }
202
IsWriter() const203 bool RdConnection::IsWriter() const
204 {
205 return isWriter_;
206 }
207
ReSetKey(const RdbStoreConfig& config)208 int32_t RdConnection::ReSetKey(const RdbStoreConfig& config)
209 {
210 if (!IsWriter()) {
211 return E_OK;
212 }
213 std::string dbPath = "";
214 int errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
215 if (errCode != E_OK) {
216 LOG_ERROR("Can not get db path.");
217 return errCode;
218 }
219 std::vector<uint8_t> key = config.GetEncryptKey();
220 std::vector<uint8_t> newKey = config.GetNewEncryptKey();
221 std::string configStr = GetConfigStr(key, config.IsEncrypt());
222 errCode = RdUtils::RdDbRekey(dbPath.c_str(), configStr.c_str(), newKey);
223 RdUtils::ClearAndZeroString(configStr);
224 key.assign(key.size(), 0);
225 newKey.assign(newKey.size(), 0);
226 if (errCode != E_OK) {
227 LOG_ERROR("ReKey failed, err = %{public}d, errno = %{public}d", errCode, errno);
228 RdbSecurityManager::GetInstance().DelKeyFile(
229 config.GetPath(), RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY);
230 return E_OK;
231 }
232 config.ChangeEncryptKey();
233 return E_OK;
234 }
235
TryCheckPoint(bool timeout)236 int32_t RdConnection::TryCheckPoint(bool timeout)
237 {
238 return E_NOT_SUPPORT;
239 }
240
LimitWalSize()241 int32_t RdConnection::LimitWalSize()
242 {
243 return E_NOT_SUPPORT;
244 }
245
ConfigLocale(const std::string& localeStr)246 int32_t RdConnection::ConfigLocale(const std::string& localeStr)
247 {
248 return E_NOT_SUPPORT;
249 }
250
CleanDirtyData(const std::string& table, uint64_t cursor)251 int32_t RdConnection::CleanDirtyData(const std::string& table, uint64_t cursor)
252 {
253 return E_NOT_SUPPORT;
254 }
255
SubscribeTableChanges(const Connection::Notifier& notifier)256 int32_t RdConnection::SubscribeTableChanges(const Connection::Notifier& notifier)
257 {
258 return E_NOT_SUPPORT;
259 }
260
GetMaxVariable() const261 int32_t RdConnection::GetMaxVariable() const
262 {
263 return MAX_VARIABLE_NUM;
264 }
265
GetJournalMode()266 int32_t RdConnection::GetJournalMode()
267 {
268 return E_NOT_SUPPORT;
269 }
270
ClearCache()271 int32_t RdConnection::ClearCache()
272 {
273 return E_NOT_SUPPORT;
274 }
275
Subscribe(const std::string& event, const std::shared_ptr<DistributedRdb::RdbStoreObserver>& observer)276 int32_t RdConnection::Subscribe(const std::string& event,
277 const std::shared_ptr<DistributedRdb::RdbStoreObserver>& observer)
278 {
279 return E_NOT_SUPPORT;
280 }
281
Unsubscribe(const std::string& event, const std::shared_ptr<DistributedRdb::RdbStoreObserver>& observer)282 int32_t RdConnection::Unsubscribe(const std::string& event,
283 const std::shared_ptr<DistributedRdb::RdbStoreObserver>& observer)
284 {
285 return E_NOT_SUPPORT;
286 }
287
Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey, bool isAsync, SlaveStatus &slaveStatus)288 int32_t RdConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
289 bool isAsync, SlaveStatus &slaveStatus)
290 {
291 if (!destEncryptKey.empty() && !config_.IsEncrypt()) {
292 return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), destEncryptKey);
293 }
294 if (config_.IsEncrypt()) {
295 std::vector<uint8_t> key = config_.GetEncryptKey();
296 int32_t ret = RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), key);
297 key.assign(key.size(), 0);
298 return ret;
299 }
300 return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), {});
301 }
302
Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey, SlaveStatus &slaveStatus)303 int32_t RdConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
304 SlaveStatus &slaveStatus)
305 {
306 if (destEncryptKey.empty()) {
307 std::vector<uint8_t> key = config_.GetEncryptKey();
308 int32_t ret = RdUtils::RdDbRestore(dbHandle_, databasePath.c_str(), key);
309 key.assign(key.size(), 0);
310 return ret;
311 }
312 return RdUtils::RdDbRestore(dbHandle_, databasePath.c_str(), destEncryptKey);
313 }
314
GenerateExchangeStrategy(const SlaveStatus &status)315 ExchangeStrategy RdConnection::GenerateExchangeStrategy(const SlaveStatus &status)
316 {
317 return ExchangeStrategy::NOT_HANDLE;
318 }
319 } // namespace NativeRdb
320 } // namespace OHOS