Add use_custom_database_format option

This commit is contained in:
Andrea Cavalli 2022-01-21 14:52:49 +01:00
parent 09b98f6b30
commit 46c0f5877d
6 changed files with 77 additions and 8 deletions

6
.gitignore vendored
View File

@ -9,3 +9,9 @@ docs/
.idea/
vcpkg/
*.tlo
td.binlog
tg_cli.log
tg_cli.log.old

View File

@ -87,6 +87,56 @@ class Global final : public ActorContext {
Status init(const TdParameters &parameters, ActorId<Td> td, unique_ptr<TdDb> td_db_ptr) TD_WARN_UNUSED_RESULT;
static bool get_use_custom_database(const std::string &database_directory) {
auto s = get_database_directory_opts(database_directory);
size_t qmarkpos;
std::string token;
size_t find_start_index = 0;
while ((qmarkpos = s.find_first_of('&'), find_start_index) != std::string::npos) {
token = s.substr(find_start_index, qmarkpos - find_start_index);
find_start_index = qmarkpos;
if ((qmarkpos = token.find_first_of('=')) != std::string::npos) {
std::string propkey = token.substr(0, qmarkpos), propval = token.substr(qmarkpos + 1);
if (propkey == "use_custom_database_format" && propval == "true") {
return true;
}
}
}
return false;
}
static std::string get_database_directory_path(const std::string &database_directory) {
if (database_directory.empty()) {
return database_directory;
}
size_t qmarkpos;
if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
std::string path = database_directory.substr(0, qmarkpos),
opts = database_directory.substr(qmarkpos + 1);
return path;
} else {
return database_directory;
}
}
static std::string get_database_directory_opts(const std::string &database_directory) {
if (database_directory.empty()) {
return database_directory;
}
size_t qmarkpos;
if ((qmarkpos = database_directory.find_first_of('?')) != std::string::npos) {
std::string path = database_directory.substr(0, qmarkpos),
opts = database_directory.substr(qmarkpos + 1);
return opts;
} else {
return "";
}
}
bool get_use_custom_database() const {
return parameters_.use_custom_db_format;
};
Slice get_dir() const {
return parameters_.database_directory;
}

View File

@ -3007,12 +3007,15 @@ td_api::object_ptr<td_api::AuthorizationState> Td::get_fake_authorization_state_
}
}
DbKey Td::as_db_key(string key) {
DbKey Td::as_db_key(string key, bool custom_db) {
// Database will still be effectively not encrypted, but
// 1. SQLite database will be protected from corruption, because that's how sqlcipher works
// 2. security through obscurity
// 3. no need for reencryption of SQLite database
if (key.empty()) {
if (custom_db) {
return DbKey::empty();
}
return DbKey::raw_key("cucumber");
}
return DbKey::raw_key(std::move(key));
@ -3080,11 +3083,11 @@ void Td::request(uint64 id, tl_object_ptr<td_api::Function> function) {
switch (function_id) {
case td_api::checkDatabaseEncryptionKey::ID: {
auto check_key = move_tl_object_as<td_api::checkDatabaseEncryptionKey>(function);
return answer_ok_query(id, init(as_db_key(std::move(check_key->encryption_key_))));
return answer_ok_query(id, init(as_db_key(std::move(check_key->encryption_key_), parameters_.use_custom_db_format)));
}
case td_api::setDatabaseEncryptionKey::ID: {
auto set_key = move_tl_object_as<td_api::setDatabaseEncryptionKey>(function);
return answer_ok_query(id, init(as_db_key(std::move(set_key->new_encryption_key_))));
return answer_ok_query(id, init(as_db_key(std::move(set_key->new_encryption_key_), parameters_.use_custom_db_format)));
}
case td_api::destroy::ID:
// need to send response synchronously before actual destroying
@ -4245,7 +4248,8 @@ Status Td::set_parameters(td_api::object_ptr<td_api::tdlibParameters> parameters
}
parameters_.use_test_dc = parameters->use_test_dc_;
parameters_.database_directory = parameters->database_directory_;
parameters_.database_directory = Global::get_database_directory_path(parameters->database_directory_);
parameters_.use_custom_db_format = Global::get_use_custom_database(parameters->database_directory_);
parameters_.files_directory = parameters->files_directory_;
parameters_.api_id = parameters->api_id_;
parameters_.api_hash = parameters->api_hash_;
@ -4310,7 +4314,7 @@ void Td::on_request(uint64 id, const td_api::checkDatabaseEncryptionKey &request
void Td::on_request(uint64 id, td_api::setDatabaseEncryptionKey &request) {
CREATE_OK_REQUEST_PROMISE();
G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_)), std::move(promise));
G()->td_db()->get_binlog()->change_key(as_db_key(std::move(request.new_encryption_key_), parameters_.use_custom_db_format), std::move(promise));
}
void Td::on_request(uint64 id, const td_api::getAuthorizationState &request) {

View File

@ -1344,7 +1344,7 @@ class Td final : public Actor {
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::addLogMessage &request);
static td_api::object_ptr<td_api::Object> do_static_request(td_api::testReturnError &request);
static DbKey as_db_key(string key);
static DbKey as_db_key(string key, bool custom_db);
Status init(DbKey key) TD_WARN_UNUSED_RESULT;
void init_options_and_network();
void init_connection_creator();

View File

@ -303,8 +303,16 @@ Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters &parameters, con
sql_connection_ = std::make_shared<SqliteConnectionSafe>(sql_database_path, key, db_instance.get_cipher_version());
sql_connection_->set(std::move(db_instance));
auto &db = sql_connection_->get();
TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
if (parameters.use_custom_db_format) {
TRY_STATUS(db.exec("PRAGMA journal_mode=OFF"));
TRY_STATUS(db.exec("PRAGMA synchronous=OFF"))
TRY_STATUS(db.exec("PRAGMA temp_store=MEMORY"));
TRY_STATUS(db.exec("PRAGMA secure_delete=0"));
TRY_STATUS(db.exec("PRAGMA mmap_size=30000000000"));
} else {
TRY_STATUS(db.exec("PRAGMA journal_mode=WAL"));
TRY_STATUS(db.exec("PRAGMA secure_delete=1"));
}
// Init databases
// Do initialization once and before everything else to avoid "database is locked" error.

View File

@ -23,6 +23,7 @@ struct TdParameters {
bool use_secret_chats = false;
bool use_chat_info_db = false;
bool use_message_db = false;
bool use_custom_db_format = false;
};
} // namespace td