mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-28 00:07:09 -05:00
Merge pull request #1628 from G10h4ck/gxs_sqlite_sqlcipher_compat
Improve SQLCipher/SQLite support
This commit is contained in:
commit
06a158e677
@ -325,13 +325,6 @@ build_sqlcipher()
|
|||||||
################################################################################
|
################################################################################
|
||||||
"
|
"
|
||||||
|
|
||||||
case "${ANDROID_NDK_ARCH}" in
|
|
||||||
"arm64")
|
|
||||||
echo sqlcipher not supported for arm64
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
B_dir="sqlcipher-${SQLCIPHER_SOURCE_VERSION}"
|
B_dir="sqlcipher-${SQLCIPHER_SOURCE_VERSION}"
|
||||||
rm -rf $B_dir
|
rm -rf $B_dir
|
||||||
|
|
||||||
@ -342,6 +335,14 @@ build_sqlcipher()
|
|||||||
|
|
||||||
tar -xf $T_file
|
tar -xf $T_file
|
||||||
cd $B_dir
|
cd $B_dir
|
||||||
|
case "${ANDROID_NDK_ARCH}" in
|
||||||
|
"arm64")
|
||||||
|
# SQLCipher config.sub is outdated and doesn't recognize newer architectures
|
||||||
|
rm config.sub
|
||||||
|
autoreconf --verbose --install --force
|
||||||
|
automake --add-missing --copy --force-missing
|
||||||
|
;;
|
||||||
|
esac
|
||||||
./configure --with-pic --build=$(sh ./config.guess) \
|
./configure --with-pic --build=$(sh ./config.guess) \
|
||||||
--host=${cArch}-linux \
|
--host=${cArch}-linux \
|
||||||
--prefix="${PREFIX}" --with-sysroot="${SYSROOT}" \
|
--prefix="${PREFIX}" --with-sysroot="${SYSROOT}" \
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2012 Christopher Evi-Parker <retroshare@lunamutt.com> *
|
* Copyright (C) 2012 Christopher Evi-Parker <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
@ -22,106 +23,143 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <memory.h>
|
#include <memory>
|
||||||
#include "util/rstime.h"
|
#include <cstdint>
|
||||||
#include <inttypes.h>
|
#include <cerrno>
|
||||||
|
|
||||||
#include "retrodb.h"
|
#include "util/rstime.h"
|
||||||
#include "rsdbbind.h"
|
#include "util/retrodb.h"
|
||||||
|
#include "util/rsdbbind.h"
|
||||||
|
#include "util/stacktrace.h"
|
||||||
|
#include "util/rsdir.h"
|
||||||
|
|
||||||
//#define RETRODB_DEBUG
|
//#define RETRODB_DEBUG
|
||||||
|
|
||||||
#ifndef NO_SQLCIPHER
|
|
||||||
#define ENABLE_ENCRYPTED_DB
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY;
|
const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY;
|
||||||
const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE;
|
const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE;
|
||||||
const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
|
||||||
RetroDb::RetroDb(const std::string &dbPath, int flags, const std::string& key) : mDb(NULL), mKey(key) {
|
RetroDb::RetroDb(const std::string& dbPath, int flags, const std::string& key):
|
||||||
|
mDb(nullptr), mKey(key)
|
||||||
|
{
|
||||||
|
bool alreadyExists = RsDirUtil::fileExists(dbPath);
|
||||||
|
|
||||||
int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, NULL);
|
int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr);
|
||||||
|
if(rc)
|
||||||
if(rc){
|
|
||||||
std::cerr << "Can't open database, Error code: " << sqlite3_errmsg(mDb)
|
|
||||||
<< std::endl;
|
|
||||||
sqlite3_close(mDb);
|
|
||||||
mDb = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_ENCRYPTED_DB
|
|
||||||
if(!mKey.empty())
|
|
||||||
{
|
|
||||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
|
||||||
|
|
||||||
if(rc){
|
|
||||||
std::cerr << "Can't key database: " << sqlite3_errmsg(mDb)
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
sqlite3_close(mDb);
|
|
||||||
mDb = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *err = NULL;
|
|
||||||
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", NULL, NULL, &err);
|
|
||||||
if (rc != SQLITE_OK)
|
|
||||||
{
|
|
||||||
std::cerr << "RetroDb::RetroDb(): Error upgrading database, error code: " << rc;
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
std::cerr << ", " << err;
|
|
||||||
}
|
|
||||||
std::cerr << std::endl;
|
|
||||||
sqlite3_free(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Test DB for correct sqlcipher version
|
|
||||||
if (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) != SQLITE_OK)
|
|
||||||
{
|
{
|
||||||
std::cerr << "RetroDb::RetroDb(): Failed to open database: " << dbPath << std::endl << "Trying with settings for sqlcipher version 3...";
|
RsErr() << __PRETTY_FUNCTION__ << " Can't open database, Error: "
|
||||||
//Reopening the database with correct settings
|
<< rc << " " << sqlite3_errmsg(mDb) << std::endl;
|
||||||
rc = sqlite3_close(mDb);
|
closeDb();
|
||||||
mDb = NULL;
|
print_stacktrace();
|
||||||
if(!rc)
|
return;
|
||||||
rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, NULL);
|
}
|
||||||
if(!rc && !mKey.empty())
|
|
||||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
if(alreadyExists)
|
||||||
if(!rc)
|
{
|
||||||
rc = sqlite3_exec(mDb, "PRAGMA kdf_iter = 64000;", NULL, NULL, NULL);
|
/* If the database has been created by a RetroShare compiled without
|
||||||
if (!rc && (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) == SQLITE_OK))
|
* SQLCipher, open it as a plain SQLite database instead of failing
|
||||||
|
* miserably. If RetroShare has been compiled without SQLCipher but the
|
||||||
|
* database seems encrypted print a meaningful error message instead of
|
||||||
|
* crashing miserably.
|
||||||
|
* At some point we could implement a migration SQLite <-> SQLCipher
|
||||||
|
* mecanism and suggest it to the user, or give the option to the user
|
||||||
|
* to choice between plain SQLite or SQLCipher database, is some cases
|
||||||
|
* such as encrypted FS it might make sense to keep SQLite even if
|
||||||
|
* SQLCipher is availble for performance, as encryption is already
|
||||||
|
* provided at FS level. */
|
||||||
|
|
||||||
|
rc = sqlite3_exec( mDb, "PRAGMA schema_version;",
|
||||||
|
nullptr, nullptr, nullptr );
|
||||||
|
if( rc == SQLITE_OK )
|
||||||
{
|
{
|
||||||
std::cerr << "\tSuccess" << std::endl;
|
#ifndef NO_SQLCIPHER
|
||||||
} else {
|
RsWarn() << __PRETTY_FUNCTION__ << " The database is not encrypted: "
|
||||||
std::cerr << "\tFailed, giving up" << std::endl;
|
<< dbPath << std::endl;
|
||||||
sqlite3_close(mDb);
|
#endif // ndef NO_SQLCIPHER
|
||||||
mDb = NULL;
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef NO_SQLCIPHER
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Error quering schema version."
|
||||||
|
<< " Are you trying to open an encrypted database without "
|
||||||
|
<< "compiling SQLCipher support?" << std::endl << std::endl;
|
||||||
|
print_stacktrace();
|
||||||
|
closeDb();
|
||||||
|
#else // def NO_SQLCIPHER
|
||||||
|
RsInfo() << __PRETTY_FUNCTION__ << " The database seems encrypted: "
|
||||||
|
<< dbPath << std::endl;
|
||||||
|
#endif // def NO_SQLCIPHER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NO_SQLCIPHER
|
||||||
|
if(!mKey.empty())
|
||||||
|
{
|
||||||
|
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Can't key database: " << rc
|
||||||
|
<< " " << sqlite3_errmsg(mDb) << std::endl;
|
||||||
|
closeDb();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
char* err = nullptr;
|
||||||
|
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", nullptr, nullptr, &err);
|
||||||
|
if (rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Error upgrading database, error "
|
||||||
|
<< "code: " << rc << " " << err << std::endl;
|
||||||
|
sqlite3_free(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test DB for correct sqlcipher version
|
||||||
|
if(sqlite3_exec(
|
||||||
|
mDb, "PRAGMA user_version;",
|
||||||
|
nullptr, nullptr, nullptr ) != SQLITE_OK)
|
||||||
|
{
|
||||||
|
RsWarn() << __PRETTY_FUNCTION__ << " Failed to open database: "
|
||||||
|
<< dbPath << std::endl;
|
||||||
|
|
||||||
|
//Reopening the database with correct settings
|
||||||
|
closeDb();
|
||||||
|
if(!rc) rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr);
|
||||||
|
if(!rc && !mKey.empty())
|
||||||
|
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||||
|
if(!rc)
|
||||||
|
rc = sqlite3_exec( mDb, "PRAGMA kdf_iter = 64000;",
|
||||||
|
nullptr, nullptr, nullptr );
|
||||||
|
if (!rc && (sqlite3_exec( mDb, "PRAGMA user_version;",
|
||||||
|
nullptr, nullptr, nullptr ) == SQLITE_OK))
|
||||||
|
{
|
||||||
|
RsInfo() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||||
|
<< "sqlcipher version 3 successed" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||||
|
<< "sqlcipher version 3 failed, giving up" << std::endl;
|
||||||
|
closeDb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ndef NO_SQLCIPHER
|
||||||
}
|
}
|
||||||
|
|
||||||
RetroDb::~RetroDb(){
|
RetroDb::~RetroDb() { closeDb(); }
|
||||||
|
|
||||||
sqlite3_close(mDb); // no-op if mDb is NULL (https://www.sqlite.org/c3ref/close.html)
|
void RetroDb::closeDb()
|
||||||
mDb = NULL ;
|
{
|
||||||
}
|
// no-op if mDb is nullptr (https://www.sqlite.org/c3ref/close.html)
|
||||||
|
int rc = sqlite3_close(mDb);
|
||||||
void RetroDb::closeDb(){
|
mDb = nullptr;
|
||||||
|
|
||||||
int rc= sqlite3_close(mDb);
|
|
||||||
mDb = NULL ;
|
|
||||||
|
|
||||||
#ifdef RETRODB_DEBUG
|
|
||||||
std::cerr << "RetroDb::closeDb(): Error code on close: " << rc << std::endl;
|
|
||||||
#else
|
|
||||||
(void)rc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
Dbg2() << __PRETTY_FUNCTION__ << " sqlite3_close return: " << rc
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TIME_LIMIT 3
|
#define TIME_LIMIT 3
|
||||||
|
@ -19,8 +19,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef RSSQLITE_H
|
#pragma once
|
||||||
#define RSSQLITE_H
|
|
||||||
|
|
||||||
#ifdef NO_SQLCIPHER
|
#ifdef NO_SQLCIPHER
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
@ -32,9 +31,10 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "rsdbbind.h"
|
|
||||||
|
|
||||||
#include "contentvalue.h"
|
#include "util/rsdebug.h"
|
||||||
|
#include "util/rsdbbind.h"
|
||||||
|
#include "util/contentvalue.h"
|
||||||
|
|
||||||
class RetroCursor;
|
class RetroCursor;
|
||||||
|
|
||||||
@ -202,6 +202,8 @@ private:
|
|||||||
|
|
||||||
sqlite3* mDb;
|
sqlite3* mDb;
|
||||||
const std::string mKey;
|
const std::string mKey;
|
||||||
|
|
||||||
|
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -318,5 +320,3 @@ public:
|
|||||||
private:
|
private:
|
||||||
sqlite3_stmt* mStmt;
|
sqlite3_stmt* mStmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RSSQLITE_H
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user