You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-05-22 10:15:16 +02:00
Add encryption capability to Info* objects.
Info objects can be stored encrypted and loaded with a cipher type and passphrase.
This commit is contained in:
@@ -35,6 +35,10 @@
|
||||
<p>Add interface objects for <proper>libxml2</proper>.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add encryption capability to <code>Info*</code> objects.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add <code>IoFilter</code> interface to <code>CipherBlock</code> object.</p>
|
||||
</release-item>
|
||||
|
||||
+4
-4
@@ -165,7 +165,7 @@ install: pgbackrest
|
||||
command/archive/common.o: command/archive/common.c command/archive/common.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
$(CC) $(CFLAGS) -c command/archive/common.c -o command/archive/common.o
|
||||
|
||||
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h compress/gzip.h compress/gzipDecompress.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h compress/gzip.h compress/gzipDecompress.h config/config.auto.h config/config.h config/define.auto.h config/define.h crypto/crypto.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
$(CC) $(CFLAGS) -c command/archive/get/file.c -o command/archive/get/file.o
|
||||
|
||||
command/archive/get/get.o: command/archive/get/get.c command/archive/common.h command/archive/get/file.h command/command.h common/assert.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
@@ -330,13 +330,13 @@ crypto/crypto.o: crypto/crypto.c common/debug.h common/error.auto.h common/error
|
||||
crypto/hash.o: crypto/hash.c common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/filter.intern.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/variant.h common/type/variantList.h crypto/crypto.h crypto/hash.h
|
||||
$(CC) $(CFLAGS) -c crypto/hash.c -o crypto/hash.o
|
||||
|
||||
info/info.o: info/info.c common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/hash.h info/info.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h version.h
|
||||
info/info.o: info/info.c common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/cipherBlock.h crypto/crypto.h crypto/hash.h info/info.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h version.h
|
||||
$(CC) $(CFLAGS) -c info/info.c -o info/info.o
|
||||
|
||||
info/infoArchive.o: info/infoArchive.c common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
info/infoArchive.o: info/infoArchive.c common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/crypto.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
$(CC) $(CFLAGS) -c info/infoArchive.c -o info/infoArchive.o
|
||||
|
||||
info/infoPg.o: info/infoPg.c common/assert.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/hash.h info/info.h info/infoPg.h postgres/interface.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
info/infoPg.o: info/infoPg.c common/assert.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/crypto.h crypto/hash.h info/info.h info/infoPg.h postgres/interface.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
|
||||
$(CC) $(CFLAGS) -c info/infoPg.c -o info/infoPg.o
|
||||
|
||||
main.o: main.c command/archive/get/get.h command/archive/push/push.h command/command.h command/help/help.h common/debug.h common/error.auto.h common/error.h common/exit.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/interface.h version.h
|
||||
|
||||
@@ -10,6 +10,7 @@ Archive Get File
|
||||
#include "compress/gzip.h"
|
||||
#include "compress/gzipDecompress.h"
|
||||
#include "config/config.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "info/infoArchive.h"
|
||||
#include "postgres/interface.h"
|
||||
#include "storage/helper.h"
|
||||
@@ -35,7 +36,8 @@ archiveGetCheck(const String *archiveFile)
|
||||
PgControl controlInfo = pgControlFromFile(cfgOptionStr(cfgOptPgPath));
|
||||
|
||||
// Attempt to load the archive info file
|
||||
InfoArchive *info = infoArchiveNew(storageRepo(), STRING_CONST(STORAGE_REPO_ARCHIVE "/" INFO_ARCHIVE_FILE), false);
|
||||
InfoArchive *info = infoArchiveNew(
|
||||
storageRepo(), STRING_CONST(STORAGE_REPO_ARCHIVE "/" INFO_ARCHIVE_FILE), false, cipherTypeNone, NULL);
|
||||
|
||||
// Loop through the pg history in case the WAL we need is not in the most recent archive id
|
||||
String *archiveId = NULL;
|
||||
|
||||
+55
-14
@@ -9,6 +9,7 @@ Info Handler
|
||||
#include "common/ini.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
#include "crypto/cipherBlock.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "info/info.h"
|
||||
#include "storage/helper.h"
|
||||
@@ -18,8 +19,14 @@ Info Handler
|
||||
Internal constants
|
||||
***********************************************************************************************************************************/
|
||||
#define INI_COPY_EXT ".copy"
|
||||
|
||||
#define INI_SECTION_BACKREST "backrest"
|
||||
STRING_STATIC(INI_SECTION_BACKREST_STR, INI_SECTION_BACKREST);
|
||||
#define INI_SECTION_CIPHER "cipher"
|
||||
STRING_STATIC(INI_SECTION_CIPHER_STR, INI_SECTION_CIPHER);
|
||||
|
||||
#define INI_KEY_CIPHER_PASS "cipher-pass"
|
||||
STRING_STATIC(INI_KEY_CIPHER_PASS_STR, INI_KEY_CIPHER_PASS);
|
||||
#define INI_KEY_FORMAT "backrest-format"
|
||||
STRING_STATIC(INI_KEY_FORMAT_STR, INI_KEY_FORMAT);
|
||||
#define INI_KEY_CHECKSUM "backrest-checksum"
|
||||
@@ -33,6 +40,7 @@ struct Info
|
||||
MemContext *memContext; // Context that contains the info
|
||||
String *fileName; // Full path name of the file
|
||||
Ini *ini; // Parsed file contents
|
||||
const String *cipherPass; // Cipher passphrase if set
|
||||
};
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@@ -174,14 +182,14 @@ infoValidInternal(
|
||||
Internal function to load the copy and check validity
|
||||
***********************************************************************************************************************************/
|
||||
static bool
|
||||
loadInternal(
|
||||
Info *this, // Info object to load parsed buffer into
|
||||
const Storage *storage,
|
||||
bool copyFile) // Is this the copy file?
|
||||
loadInternal(Info *this, const Storage *storage, bool copyFile, CipherType cipherType, const String *cipherPass)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(INFO, this);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, copyFile);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace)
|
||||
FUNCTION_DEBUG_PARAM(INFO, this); // Info object to load parsed buffer into
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, storage);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, copyFile); // Is this the copy file?
|
||||
FUNCTION_DEBUG_PARAM(ENUM, cipherType);
|
||||
// cipherPass omitted for security
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(this != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
@@ -193,7 +201,18 @@ loadInternal(
|
||||
String *fileName = copyFile ? strCat(strDup(this->fileName), INI_COPY_EXT) : this->fileName;
|
||||
|
||||
// Attempt to load the file
|
||||
Buffer *buffer = storageGetNP(storageNewReadP(storage, fileName, .ignoreMissing = true));
|
||||
StorageFileRead *infoRead = storageNewReadP(storage, fileName, .ignoreMissing = true);
|
||||
|
||||
if (cipherType != cipherTypeNone)
|
||||
{
|
||||
ioReadFilterGroupSet(
|
||||
storageFileReadIo(infoRead),
|
||||
ioFilterGroupAdd(
|
||||
ioFilterGroupNew(), cipherBlockFilter(cipherBlockNew(cipherModeDecrypt, cipherType, bufNewStr(cipherPass),
|
||||
NULL))));
|
||||
}
|
||||
|
||||
Buffer *buffer = storageGetNP(infoRead);
|
||||
|
||||
// If the file exists, parse and validate it
|
||||
if (buffer != NULL)
|
||||
@@ -217,12 +236,13 @@ Load an Info object
|
||||
// ??? The file MUST exist currently, so this is not actually creating the object - rather it is loading it
|
||||
***********************************************************************************************************************************/
|
||||
Info *
|
||||
infoNew(
|
||||
const Storage *storage,
|
||||
const String *fileName) // Full path/filename to load
|
||||
infoNew(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileName);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, storage);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileName); // Full path/filename to load
|
||||
FUNCTION_DEBUG_PARAM(ENUM, cipherType);
|
||||
// cipherPass omitted for security
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(fileName != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
@@ -239,9 +259,9 @@ infoNew(
|
||||
this->fileName = strDup(fileName);
|
||||
|
||||
// Attempt to load the main file. If it does not exist or is invalid, try to load the copy.
|
||||
if (!loadInternal(this, storage, false))
|
||||
if (!loadInternal(this, storage, false, cipherType, cipherPass))
|
||||
{
|
||||
if (!loadInternal(this, storage, true))
|
||||
if (!loadInternal(this, storage, true, cipherType, cipherPass))
|
||||
{
|
||||
THROW_FMT(
|
||||
FileMissingError, "unable to open %s or %s",
|
||||
@@ -249,6 +269,15 @@ infoNew(
|
||||
strPtr(strCat(storagePathNP(storage, this->fileName), INI_COPY_EXT)));
|
||||
}
|
||||
}
|
||||
|
||||
// Load the cipher passphrase if it exists
|
||||
String *cipherPass = varStr(iniGetDefault(this->ini, INI_SECTION_CIPHER_STR, INI_KEY_CIPHER_PASS_STR, NULL));
|
||||
|
||||
if (cipherPass != NULL)
|
||||
{
|
||||
this->cipherPass = strSubN(cipherPass, 1, strSize(cipherPass) - 2);
|
||||
strFree(cipherPass);
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
@@ -259,6 +288,18 @@ infoNew(
|
||||
/***********************************************************************************************************************************
|
||||
Accessor functions
|
||||
***********************************************************************************************************************************/
|
||||
const String *
|
||||
infoCipherPass(const Info *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INFO, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, this->cipherPass);
|
||||
}
|
||||
|
||||
Ini *
|
||||
infoIni(const Info *this)
|
||||
{
|
||||
|
||||
+3
-1
@@ -10,17 +10,19 @@ Object type
|
||||
typedef struct Info Info;
|
||||
|
||||
#include "common/ini.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "storage/storage.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Constructor
|
||||
***********************************************************************************************************************************/
|
||||
Info *infoNew(const Storage *storage, const String *fileName);
|
||||
Info *infoNew(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters
|
||||
***********************************************************************************************************************************/
|
||||
const String *infoCipherPass(const Info *this);
|
||||
String *infoFileName(const Info *this);
|
||||
Ini *infoIni(const Info *this);
|
||||
|
||||
|
||||
+20
-2
@@ -30,11 +30,14 @@ Create a new InfoArchive object
|
||||
// ??? Need loadFile parameter
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *
|
||||
infoArchiveNew(const Storage *storage, const String *fileName, bool ignoreMissing)
|
||||
infoArchiveNew(const Storage *storage, const String *fileName, bool ignoreMissing, CipherType cipherType, const String *cipherPass)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, storage);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileName);
|
||||
FUNCTION_DEBUG_PARAM(BOOL, ignoreMissing);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, cipherType);
|
||||
// cipherPass omitted for security
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(fileName != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
@@ -50,7 +53,7 @@ infoArchiveNew(const Storage *storage, const String *fileName, bool ignoreMissin
|
||||
// Catch file missing error and add archive-specific hints before rethrowing
|
||||
TRY_BEGIN()
|
||||
{
|
||||
this->infoPg = infoPgNew(storage, fileName, infoPgArchive);
|
||||
this->infoPg = infoPgNew(storage, fileName, infoPgArchive, cipherType, cipherPass);
|
||||
}
|
||||
CATCH(FileMissingError)
|
||||
{
|
||||
@@ -132,6 +135,21 @@ infoArchiveId(const InfoArchive *this)
|
||||
FUNCTION_TEST_RESULT(STRING, this->archiveId);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Return the cipher passphrase
|
||||
***********************************************************************************************************************************/
|
||||
const String *
|
||||
infoArchiveCipherPass(const InfoArchive *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INFO_ARCHIVE, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, infoPgCipherPass(this->infoPg));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get PostgreSQL info
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
@@ -10,6 +10,7 @@ Object type
|
||||
typedef struct InfoArchive InfoArchive;
|
||||
|
||||
#include "common/type/string.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "info/infoPg.h"
|
||||
#include "storage/storage.h"
|
||||
|
||||
@@ -21,7 +22,8 @@ Archive info filename
|
||||
/***********************************************************************************************************************************
|
||||
Constructor
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *infoArchiveNew(const Storage *storage, const String *fileName, bool ignoreMissing);
|
||||
InfoArchive *infoArchiveNew(
|
||||
const Storage *storage, const String *fileName, bool ignoreMissing, CipherType cipherType, const String *cipherPass);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
@@ -32,6 +34,7 @@ void infoArchiveCheckPg(const InfoArchive *this, unsigned int pgVersion, uint64_
|
||||
Getters
|
||||
***********************************************************************************************************************************/
|
||||
const String *infoArchiveId(const InfoArchive *this);
|
||||
const String *infoArchiveCipherPass(const InfoArchive *this);
|
||||
InfoPg *infoArchivePg(const InfoArchive *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
|
||||
+21
-2
@@ -58,10 +58,14 @@ Load an InfoPg object
|
||||
??? Currently this assumes the file exists and loads data from it
|
||||
***********************************************************************************************************************************/
|
||||
InfoPg *
|
||||
infoPgNew(const Storage *storage, const String *fileName, InfoPgType type)
|
||||
infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STORAGE, storage);
|
||||
FUNCTION_DEBUG_PARAM(STRING, fileName);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, type);
|
||||
FUNCTION_DEBUG_PARAM(ENUM, cipherType);
|
||||
// cipherPass omitted for security
|
||||
|
||||
FUNCTION_DEBUG_ASSERT(fileName != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
@@ -73,7 +77,7 @@ infoPgNew(const Storage *storage, const String *fileName, InfoPgType type)
|
||||
// Create object
|
||||
this = memNew(sizeof(InfoPg));
|
||||
this->memContext = MEM_CONTEXT_NEW();
|
||||
this->info = infoNew(storage, fileName);
|
||||
this->info = infoNew(storage, fileName, cipherType, cipherPass);
|
||||
|
||||
// Get the pg history list
|
||||
this->history = lstNew(sizeof(InfoPgData));
|
||||
@@ -171,6 +175,21 @@ infoPgArchiveId(const InfoPg *this, unsigned int pgDataIdx)
|
||||
FUNCTION_DEBUG_RESULT(STRING, strNewFmt("%s-%u", strPtr(pgVersionToStr(pgData.version)), pgData.id));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Return the cipher passphrase
|
||||
***********************************************************************************************************************************/
|
||||
const String *
|
||||
infoPgCipherPass(const InfoPg *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INFO_PG, this);
|
||||
|
||||
FUNCTION_TEST_ASSERT(this != NULL);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(CONST_STRING, infoCipherPass(this->info));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Return a structure of the Postgres data from a specific index
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
+3
-2
@@ -11,6 +11,7 @@ typedef struct InfoPg InfoPg;
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "crypto/crypto.h"
|
||||
#include "storage/storage.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@@ -38,7 +39,7 @@ typedef enum
|
||||
/***********************************************************************************************************************************
|
||||
Constructor
|
||||
***********************************************************************************************************************************/
|
||||
InfoPg *infoPgNew(const Storage *storage, const String *fileName, InfoPgType type);
|
||||
InfoPg *infoPgNew(const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
@@ -49,7 +50,7 @@ void infoPgAdd(InfoPg *this, const InfoPgData *infoPgData);
|
||||
Getters
|
||||
***********************************************************************************************************************************/
|
||||
String *infoPgArchiveId(const InfoPg *this, unsigned int pgDataIdx);
|
||||
|
||||
const String *infoPgCipherPass(const InfoPg *this);
|
||||
InfoPgData infoPgData(const InfoPg *this, unsigned int pgDataIdx);
|
||||
InfoPgData infoPgDataCurrent(const InfoPg *this);
|
||||
unsigned int infoPgDataTotal(const InfoPg *this);
|
||||
|
||||
@@ -133,9 +133,9 @@ P00 DEBUG: storage/storage::storageGet: => {used: 512, size: 512, limit: <o
|
||||
P00 DEBUG: postgres/interface::pgControlFromFile: => {version: 90400, systemId: 1000000000000000094, walSegmentSize: 16777216, pageChecksum: true}
|
||||
P00 DEBUG: storage/driver/posix/storage::storageDriverPosixNew: (path: {"[TEST_PATH]/db-master/repo"}, modeFile: 0640, modePath: 0750, write: false, pathExpressionFunction: (function *))
|
||||
P00 DEBUG: storage/driver/posix/storage::storageDriverPosixNew: => {StorageDriverPosix}
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: (fileName: {"<REPO:ARCHIVE>/archive.info"}, ignoreMissing: false)
|
||||
P00 DEBUG: info/infoPg::infoPgNew: (fileName: {"<REPO:ARCHIVE>/archive.info"})
|
||||
P00 DEBUG: info/info::infoNew: (fileName: {"<REPO:ARCHIVE>/archive.info"})
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, ignoreMissing: false, cipherType: 0)
|
||||
P00 DEBUG: info/infoPg::infoPgNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, type: 0, cipherType: 0)
|
||||
P00 DEBUG: info/info::infoNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, cipherType: 0)
|
||||
P00 DEBUG: info/info::infoNew: => {Info}
|
||||
P00 DEBUG: info/infoPg::infoPgNew: => {InfoPg}
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: => {InfoArchive}
|
||||
@@ -175,9 +175,9 @@ P00 DEBUG: storage/storage::storageGet: => {used: 512, size: 512, limit: <o
|
||||
P00 DEBUG: postgres/interface::pgControlFromFile: => {version: 90400, systemId: 1000000000000000094, walSegmentSize: 16777216, pageChecksum: true}
|
||||
P00 DEBUG: storage/driver/posix/storage::storageDriverPosixNew: (path: {"[TEST_PATH]/db-master/repo"}, modeFile: 0640, modePath: 0750, write: false, pathExpressionFunction: (function *))
|
||||
P00 DEBUG: storage/driver/posix/storage::storageDriverPosixNew: => {StorageDriverPosix}
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: (fileName: {"<REPO:ARCHIVE>/archive.info"}, ignoreMissing: false)
|
||||
P00 DEBUG: info/infoPg::infoPgNew: (fileName: {"<REPO:ARCHIVE>/archive.info"})
|
||||
P00 DEBUG: info/info::infoNew: (fileName: {"<REPO:ARCHIVE>/archive.info"})
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, ignoreMissing: false, cipherType: 0)
|
||||
P00 DEBUG: info/infoPg::infoPgNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, type: 0, cipherType: 0)
|
||||
P00 DEBUG: info/info::infoNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, cipherType: 0)
|
||||
P00 DEBUG: info/info::infoNew: => {Info}
|
||||
P00 DEBUG: info/infoPg::infoPgNew: => {InfoPg}
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: => {InfoArchive}
|
||||
|
||||
@@ -550,9 +550,9 @@ P00 DEBUG: storage/storage::storageGet: => {used: 512, size: 512, limit: <o
|
||||
P00 DEBUG: postgres/interface::pgControlFromFile: => {version: 90300, systemId: 1000000000000000093, walSegmentSize: 16777216, pageChecksum: true}
|
||||
P00 DEBUG: storage/driver/posix/storage::storageDriverPosixNew: (path: {"[TEST_PATH]/db-master/repo"}, modeFile: 0640, modePath: 0750, write: false, pathExpressionFunction: (function *))
|
||||
P00 DEBUG: storage/driver/posix/storage::storageDriverPosixNew: => {StorageDriverPosix}
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: (fileName: {"<REPO:ARCHIVE>/archive.info"}, ignoreMissing: false)
|
||||
P00 DEBUG: info/infoPg::infoPgNew: (fileName: {"<REPO:ARCHIVE>/archive.info"})
|
||||
P00 DEBUG: info/info::infoNew: (fileName: {"<REPO:ARCHIVE>/archive.info"})
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, ignoreMissing: false, cipherType: 0)
|
||||
P00 DEBUG: info/infoPg::infoPgNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, type: 0, cipherType: 0)
|
||||
P00 DEBUG: info/info::infoNew: (storage: {type: posix, path: {"[TEST_PATH]/db-master/repo"}, write: false}, fileName: {"<REPO:ARCHIVE>/archive.info"}, cipherType: 0)
|
||||
P00 DEBUG: info/info::infoNew: => {Info}
|
||||
P00 DEBUG: info/infoPg::infoPgNew: => {InfoPg}
|
||||
P00 DEBUG: info/infoArchive::infoArchiveNew: => {InfoArchive}
|
||||
|
||||
@@ -17,7 +17,7 @@ testRun(void)
|
||||
String *fileName = strNewFmt("%s/test.ini", testPath());
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
infoArchiveNew(storageLocal(), fileName, true), FileMissingError,
|
||||
infoArchiveNew(storageLocal(), fileName, true, cipherTypeNone, NULL), FileMissingError,
|
||||
"unable to open %s/test.ini or %s/test.ini.copy\n"
|
||||
"HINT: archive.info does not exist but is required to push/get WAL segments.\n"
|
||||
"HINT: is archive_command configured in postgresql.conf?\n"
|
||||
@@ -47,9 +47,10 @@ testRun(void)
|
||||
|
||||
InfoArchive *info = NULL;
|
||||
|
||||
TEST_ASSIGN(info, infoArchiveNew(storageLocal(), fileName, true), " new archive info");
|
||||
TEST_ASSIGN(info, infoArchiveNew(storageLocal(), fileName, true, cipherTypeNone, NULL), " new archive info");
|
||||
TEST_RESULT_STR(strPtr(infoArchiveId(info)), "9.4-1", " archiveId set");
|
||||
TEST_RESULT_PTR(infoArchivePg(info), info->infoPg, " infoPg set");
|
||||
TEST_RESULT_PTR(infoArchiveCipherPass(info), NULL, " no cipher passphrase");
|
||||
|
||||
// Check PG version
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -36,7 +36,8 @@ testRun(void)
|
||||
|
||||
InfoPg *infoPg = NULL;
|
||||
|
||||
TEST_ASSIGN(infoPg, infoPgNew(storageLocal(), fileName, infoPgArchive), "new infoPg archive - load file");
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgNew(storageLocal(), fileName, infoPgArchive, cipherTypeNone, NULL), "new infoPg archive - load file");
|
||||
|
||||
TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added");
|
||||
|
||||
@@ -48,6 +49,7 @@ testRun(void)
|
||||
TEST_RESULT_INT(infoPgData.controlVersion, 0, " control-version not set");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " check pg data total");
|
||||
TEST_RESULT_STR(strPtr(infoPgArchiveId(infoPg, 0)), "9.4-1", " check pg archive id");
|
||||
TEST_RESULT_PTR(infoPgCipherPass(infoPg), NULL, " no cipher passphrase");
|
||||
|
||||
// Backup info
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -72,7 +74,8 @@ testRun(void)
|
||||
|
||||
TEST_RESULT_VOID(storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), bufNewStr(content)), "put info to file");
|
||||
|
||||
TEST_ASSIGN(infoPg, infoPgNew(storageLocal(), fileName, infoPgBackup), "new infoPg backup - load file");
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgNew(storageLocal(), fileName, infoPgBackup, cipherTypeNone, NULL), "new infoPg backup - load file");
|
||||
|
||||
TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added");
|
||||
|
||||
@@ -108,7 +111,8 @@ testRun(void)
|
||||
|
||||
TEST_RESULT_VOID(storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), bufNewStr(content)), "put info to file");
|
||||
|
||||
TEST_ASSIGN(infoPg, infoPgNew(storageLocal(), fileName, infoPgManifest), "new infoPg manifest - load file");
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgNew(storageLocal(), fileName, infoPgManifest, cipherTypeNone, NULL), "new infoPg manifest - load file");
|
||||
|
||||
TEST_RESULT_INT(lstSize(infoPg->history), 2, "history record added");
|
||||
|
||||
@@ -137,9 +141,10 @@ testRun(void)
|
||||
|
||||
// Errors
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR(infoPgNew(storageLocal(), fileName, 10), AssertError, "invalid InfoPg type 10");
|
||||
TEST_ERROR(infoPgNew(storageLocal(), fileName, 10, cipherTypeNone, NULL), AssertError, "invalid InfoPg type 10");
|
||||
TEST_ERROR(
|
||||
infoPgNew(storageLocal(), NULL, infoPgManifest), AssertError, "function debug assertion 'fileName != NULL' failed");
|
||||
infoPgNew(storageLocal(), NULL, infoPgManifest, cipherTypeNone, NULL), AssertError,
|
||||
"function debug assertion 'fileName != NULL' failed");
|
||||
|
||||
TEST_ERROR(infoPgDataCurrent(NULL), AssertError, "function debug assertion 'this != NULL' failed");
|
||||
|
||||
|
||||
@@ -38,27 +38,55 @@ testRun(void)
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
String *missingInfoError = strNewFmt("unable to open %s or %s", strPtr(fileName), strPtr(fileNameCopy));
|
||||
|
||||
TEST_ERROR(infoNew(storageLocal(), fileName), FileMissingError, strPtr(missingInfoError));
|
||||
TEST_ERROR(infoNew(storageLocal(), fileName, cipherTypeNone, NULL), FileMissingError, strPtr(missingInfoError));
|
||||
|
||||
// Only copy exists and one is required
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileNameCopy), bufNewStr(content)), "put info.copy to file");
|
||||
|
||||
TEST_ASSIGN(info, infoNew(storageLocal(), fileName), "infoNew() - load copy file");
|
||||
TEST_ASSIGN(info, infoNew(storageLocal(), fileName, cipherTypeNone, NULL), "infoNew() - load copy file");
|
||||
TEST_RESULT_STR(strPtr(infoFileName(info)), strPtr(fileName), " infoFileName() is set");
|
||||
|
||||
TEST_RESULT_PTR(infoIni(info), info->ini, " infoIni() returns pointer to info->ini");
|
||||
TEST_RESULT_PTR(infoCipherPass(info), NULL, " cipherPass is not set");
|
||||
|
||||
// Remove the copy and store only the main info file. One is required.
|
||||
// Remove the copy and store only the main info file and encrypt it. One is required.
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
storageMoveNP(
|
||||
storageLocal(), storageNewReadNP(storageLocal(), fileNameCopy), storageNewWriteNP(storageLocalWrite(), fileName));
|
||||
StorageFileWrite *infoWrite = storageNewWriteNP(storageLocalWrite(), fileName);
|
||||
|
||||
ioWriteFilterGroupSet(
|
||||
storageFileWriteIo(infoWrite),
|
||||
ioFilterGroupAdd(
|
||||
ioFilterGroupNew(),
|
||||
cipherBlockFilter(cipherBlockNew(cipherModeEncrypt, cipherTypeAes256Cbc, bufNewStr(strNew("12345678")), NULL))));
|
||||
|
||||
storageRemoveNP(storageLocalWrite(), fileNameCopy);
|
||||
storagePutNP(
|
||||
infoWrite,
|
||||
bufNewStr(
|
||||
strNew(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"9d2f6dce339751e1a056187fad67d2834b3d4ab3\"\n"
|
||||
"backrest-format=5\n"
|
||||
"backrest-version=\"2.04\"\n"
|
||||
"\n"
|
||||
"[cipher]\n"
|
||||
"cipher-pass=\"ABCDEFGH\"\n"
|
||||
"\n"
|
||||
"[db]\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6569239123849665679\n"
|
||||
"db-version=\"9.4\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.4\"}\n")));
|
||||
|
||||
// Only main info exists and is required
|
||||
TEST_ASSIGN(info, infoNew(storageLocal(), fileName), "infoNew() - load file");
|
||||
TEST_ASSIGN(info, infoNew(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("12345678")), "infoNew() - load file");
|
||||
|
||||
TEST_RESULT_STR(strPtr(infoFileName(info)), strPtr(fileName), " infoFileName() is set");
|
||||
TEST_RESULT_STR(strPtr(infoCipherPass(info)), "ABCDEFGH", " cipherPass is set");
|
||||
|
||||
// Invalid format
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -87,7 +115,7 @@ testRun(void)
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), bufNewStr(content)), "put invalid br format to file");
|
||||
|
||||
TEST_ERROR(infoNew(storageLocal(), fileName), FileMissingError, strPtr(missingInfoError));
|
||||
TEST_ERROR(infoNew(storageLocal(), fileName, cipherTypeNone, NULL), FileMissingError, strPtr(missingInfoError));
|
||||
harnessLogResult(
|
||||
strPtr(
|
||||
strNewFmt("P00 WARN: invalid format in '%s', expected %d but found %d", strPtr(fileName), REPOSITORY_FORMAT, 4)));
|
||||
@@ -95,7 +123,7 @@ testRun(void)
|
||||
storageCopyNP(storageNewReadNP(storageLocal(), fileName), storageNewWriteNP(storageLocalWrite(), fileNameCopy));
|
||||
|
||||
TEST_ERROR(
|
||||
infoNew(storageLocal(), fileName), FormatError,
|
||||
infoNew(storageLocal(), fileName, cipherTypeNone, NULL), FormatError,
|
||||
strPtr(strNewFmt("invalid format in '%s', expected %d but found %d", strPtr(fileName), REPOSITORY_FORMAT, 4)));
|
||||
harnessLogResult(
|
||||
strPtr(
|
||||
@@ -150,7 +178,7 @@ testRun(void)
|
||||
|
||||
// Copy file error
|
||||
TEST_ERROR(
|
||||
infoNew(storageLocal(), fileName), ChecksumError,
|
||||
infoNew(storageLocal(), fileName, cipherTypeNone, NULL), ChecksumError,
|
||||
strPtr(strNewFmt("invalid checksum in '%s', expected '%s' but found '%s'", strPtr(fileName),
|
||||
"4306ec205f71417c301e403c4714090e61c8a736", "4306ec205f71417c301e403c4714090e61c8a999")));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user