1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-10-23 21:28:56 +03:00

Pass a cipher spec rather than a type and passphrase.

The cipher type and passphrase were separate parameters in every function that reads or writes an encrypted file, every info file load and save, and every protocol message that hands a file to a local process. Anything added alongside them meant changing all of it again.

A cipher spec keeps them together. The pass is a buffer rather than a string so an absent pass is simply NULL, and it is copied into the object so the caller is free to release whatever it was read from. The spec is packed and unpacked as a unit for the protocol and writes nothing but the type when there is no cipher.

The digest the key derives with was a parameter of the block cipher filter, packed with every filter that crossed the protocol, and nothing but the tests ever set it. It is gone and the key derives with SHA-1 where that happens, since the spec is where the choice would go if there is ever more than one.

The specs form a chain. cfgCipherSpecMainIdx() builds one from the options and caches it per repository, the info files are read with that, and each info file carries the spec for the files that depend on it, so nothing below the info files consults the options again. The cache is filled the first time a spec is asked for, so a command has to get the repo storage before then, since that is what pulls the cipher options down from a remote repository.

An info file stores a pass but not a type, so the spec it carries takes the type of the spec the file was read with. That spec is never NULL, and is none when the file has no pass, so it can be handed on without a check.

A spec is named for what it opens: cipherSpecMain from the configuration, cipherSpecArchive from archive.info, cipherSpecManifest from backup.info, and cipherSpecBackup from the manifest. That turned up names that said the opposite of what they held, since what backup called the backup passphrase is what opens manifests, and restore documented the passphrase it loads the manifest with as being for backup files.

The test harness takes a spec as well, so the storage and backup harnesses no longer accept a type and pass pair, and the rule that a missing pass meant the main test pass is now spelled out in TEST_CIPHER_SPEC.
This commit is contained in:
David Steele
2026-08-18 10:23:25 +07:00
committed by GitHub
parent 078489fa34
commit b9b58a17db
92 changed files with 1087 additions and 843 deletions

View File

@@ -52,6 +52,17 @@
</release-improvement-list>
<release-development-list>
<release-item>
<github-pull-request id="2826"/>
<release-item-contributor-list>
<release-item-contributor id="david.steele"/>
<release-item-reviewer id="douglas.j.hunley"/>
</release-item-contributor-list>
<p>Pass a cipher spec rather than a type and passphrase.</p>
</release-item>
<release-item>
<github-pull-request id="2817"/>

View File

@@ -56,11 +56,8 @@ cmdAnnotate(void)
storageRepoIdx(repoIdx);
// Attempt to load the backup info file
const CipherType repoCipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx);
InfoBackup *infoBackup = infoBackupLoadFileReconstruct(
storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, repoCipherType,
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
if (infoBackupLabelExists(infoBackup, backupLabel))
{
@@ -75,9 +72,7 @@ cmdAnnotate(void)
infoBackupDataAnnotationSet(infoBackup, backupLabel, cfgOptionKv(cfgOptAnnotation));
// Write the updated backup info
infoBackupSaveFile(
infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, repoCipherType,
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
}
}
CATCH_ANY()

View File

@@ -54,11 +54,11 @@ archiveGetFile(
storage, walDestination, .noCreatePath = true, .noSyncFile = true, .noSyncPath = true, .noAtomic = true);
// If there is a cipher then add the decrypt filter
if (actual->cipherType != cipherTypeNone)
if (cipherSpecType(actual->cipherSpecArchive) != cipherTypeNone)
{
ioFilterGroupAdd(
ioWriteFilterGroup(storageWriteIo(destination)),
cipherBlockNewP(cipherModeDecrypt, actual->cipherType, BUFSTR(actual->cipherPassArchive)));
cipherBlockNewP(cipherModeDecrypt, actual->cipherSpecArchive));
compressible = false;
}

View File

@@ -4,7 +4,7 @@ Archive Get File
#ifndef COMMAND_ARCHIVE_GET_FILE_H
#define COMMAND_ARCHIVE_GET_FILE_H
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
#include "common/type/string.h"
#include "storage/storage.h"
@@ -17,8 +17,7 @@ typedef struct ArchiveGetFile
const String *file; // File in the repo (with path, checksum, ext, etc.)
unsigned int repoIdx; // Repo idx
const String *archiveId; // Repo archive id
CipherType cipherType; // Repo cipher type
const String *cipherPassArchive; // Repo archive cipher pass
const CipherSpec *cipherSpecArchive; // Repo archive cipher spec
} ArchiveGetFile;
typedef struct ArchiveGetFileResult

View File

@@ -94,8 +94,7 @@ typedef struct ArchiveGetFindCacheArchive
typedef struct ArchiveGetFindCacheRepo
{
unsigned int repoIdx;
CipherType cipherType; // Repo cipher type
const String *cipherPassArchive; // Repo archive cipher pass
const CipherSpec *cipherSpecArchive; // Repo archive cipher spec
List *archiveList; // Cached list of archiveIds and associated paths
StringList *warnList; // Track repo warnings so each is only reported once
} ArchiveGetFindCacheRepo;
@@ -213,8 +212,7 @@ archiveGetFind(
strZ(strLstGet(segmentList, segmentIdx))),
.repoIdx = cacheRepo->repoIdx,
.archiveId = cacheArchive->archiveId,
.cipherType = cacheRepo->cipherType,
.cipherPassArchive = cacheRepo->cipherPassArchive,
.cipherSpecArchive = cacheRepo->cipherSpecArchive,
};
lstAdd(matchList, &archiveGetFile);
@@ -235,8 +233,7 @@ archiveGetFind(
.file = strNewFmt("%s/%s", strZ(cacheArchive->archiveId), strZ(archiveFileRequest)),
.repoIdx = cacheRepo->repoIdx,
.archiveId = cacheArchive->archiveId,
.cipherType = cacheRepo->cipherType,
.cipherPassArchive = cacheRepo->cipherPassArchive,
.cipherSpecArchive = cacheRepo->cipherSpecArchive,
};
lstAdd(matchList, &archiveGetFile);
@@ -408,20 +405,18 @@ archiveGetCheck(const StringList *const archiveRequestList)
ArchiveGetFindCacheRepo cacheRepo =
{
.repoIdx = repoIdx,
.cipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
.archiveList = lstNewP(sizeof(ArchiveGetFindCacheArchive)),
.warnList = strLstNew(),
};
// Attempt to load the archive info file
const InfoArchive *const info = infoArchiveLoadFile(
storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cacheRepo.cipherType,
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
// Copy cipher pass into the result list context once rather than making a copy per candidate file later
// Build cipher spec in the result list context once rather than rebuilding it per candidate file later
MEM_CONTEXT_BEGIN(lstMemContext(result.archiveFileMapList))
{
cacheRepo.cipherPassArchive = strDup(infoArchiveCipherPass(info));
cacheRepo.cipherSpecArchive = cipherSpecDup(infoArchiveCipherSpec(info));
}
MEM_CONTEXT_END();
@@ -933,8 +928,7 @@ archiveGetAsyncCallback(void *const data, const unsigned int clientIdx)
pckWriteStrP(param, actual->file);
pckWriteU32P(param, actual->repoIdx);
pckWriteStrP(param, actual->archiveId);
pckWriteU64P(param, actual->cipherType);
pckWriteStrP(param, actual->cipherPassArchive);
cipherSpecPack(param, actual->cipherSpecArchive);
}
MEM_CONTEXT_PRIOR_BEGIN()

View File

@@ -38,8 +38,7 @@ archiveGetFileProtocol(PackRead *const param)
ArchiveGetFile actual = {.file = pckReadStrP(param)};
actual.repoIdx = pckReadU32P(param);
actual.archiveId = pckReadStrP(param);
actual.cipherType = pckReadU64P(param);
actual.cipherPassArchive = pckReadStrP(param);
actual.cipherSpecArchive = cipherSpecNewPack(param);
lstAdd(actualList, &actual);
}

View File

@@ -266,11 +266,11 @@ archivePushFile(
.compressible = compressible);
// If there is a cipher then add the encrypt filter
if (repoData->cipherType != cipherTypeNone)
if (cipherSpecType(repoData->cipherSpecArchive) != cipherTypeNone)
{
ioFilterGroupAdd(
ioWriteFilterGroup(storageWriteIo(destination[repoListIdx])),
cipherBlockNewP(cipherModeEncrypt, repoData->cipherType, BUFSTR(repoData->cipherPass)));
cipherBlockNewP(cipherModeEncrypt, repoData->cipherSpecArchive));
}
}
}

View File

@@ -5,7 +5,7 @@ Archive Push File
#define COMMAND_ARCHIVE_PUSH_FILE_H
#include "common/compress/helper.h"
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
#include "common/type/string.h"
#include "storage/storage.h"
@@ -17,8 +17,7 @@ typedef struct ArchivePushFileRepoData
{
unsigned int repoIdx;
const String *archiveId;
CipherType cipherType;
const String *cipherPass;
const CipherSpec *cipherSpecArchive; // Repo archive cipher spec
} ArchivePushFileRepoData;
/***********************************************************************************************************************************

View File

@@ -48,8 +48,7 @@ archivePushFileProtocol(PackRead *const param)
ArchivePushFileRepoData repo = {.repoIdx = pckReadU32P(param)};
repo.archiveId = pckReadStrP(param);
repo.cipherType = pckReadU64P(param);
repo.cipherPass = pckReadStrP(param);
repo.cipherSpecArchive = cipherSpecNewPack(param);
pckReadObjEndP(param);
lstAdd(repoList, &repo);

View File

@@ -230,13 +230,9 @@ archivePushCheck(const bool pgPathSet)
// Get the repo storage in case it is remote and encryption settings need to be pulled down
storageRepoIdx(repoIdx);
// Get cipher type
const CipherType repoCipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx);
// Attempt to load the archive info file
const InfoArchive *const info = infoArchiveLoadFile(
storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, repoCipherType,
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
// Get archive id for the most recent version -- archive-push will only operate against the most recent version
const String *const archiveId = infoPgArchiveId(infoArchivePg(info), infoPgDataCurrentId(infoArchivePg(info)));
@@ -268,8 +264,7 @@ archivePushCheck(const bool pgPathSet)
{
.repoIdx = repoIdx,
.archiveId = strDup(archiveId),
.cipherType = repoCipherType,
.cipherPass = strDup(infoArchiveCipherPass(info)),
.cipherSpecArchive = cipherSpecDup(infoArchiveCipherSpec(info)),
};
lstAdd(result.repoList, &archivePushFileRepoData);
@@ -493,8 +488,7 @@ archivePushAsyncCallback(void *const data, const unsigned int clientIdx)
pckWriteObjBeginP(param);
pckWriteU32P(param, data->repoIdx);
pckWriteStrP(param, data->archiveId);
pckWriteU64P(param, data->cipherType);
pckWriteStrP(param, data->cipherPass);
cipherSpecPack(param, data->cipherSpecArchive);
pckWriteObjEndP(param);
}

View File

@@ -165,9 +165,7 @@ backupInit(const InfoBackup *const infoBackup)
// Get archive info
if (cfgOptionBool(cfgOptArchiveCheck))
{
result->archiveInfo = infoArchiveLoadFile(
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType),
cfgOptionStrNull(cfgOptRepoCipherPass));
result->archiveInfo = infoArchiveLoadFile(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMain());
result->archiveId = infoArchiveId(result->archiveInfo);
}
@@ -207,10 +205,9 @@ cmdBackup(void)
storageRepo();
// Load backup.info
InfoBackup *const infoBackup = infoBackupLoadFileReconstruct(
storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType), cfgOptionStrNull(cfgOptRepoCipherPass));
InfoBackup *const infoBackup = infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMain());
const InfoPgData infoPg = infoPgDataCurrent(infoBackupPg(infoBackup));
const String *const cipherPassBackup = infoPgCipherPass(infoBackupPg(infoBackup));
const CipherSpec *const cipherSpecManifest = infoBackupCipherSpec(infoBackup);
// Get pg storage and database objects
BackupData *const backupData = backupInit(infoBackup);
@@ -239,14 +236,14 @@ cmdBackup(void)
// Build an incremental backup if type is not full (manifestPrior will be freed in this call)
if (!backupBuildIncr(infoBackup, manifest, manifestPrior, backupStartResult.walSegmentName))
manifestCipherSubPassSet(manifest, cipherPassGen(cfgOptionStrId(cfgOptRepoCipherType)));
manifestCipherSpecSet(manifest, cipherSpecGen(cfgOptionStrId(cfgOptRepoCipherType)));
// Set delta if it is not already set and the manifest requires it
if (!cfgOptionBool(cfgOptDelta) && varBool(manifestData(manifest)->backupOptionDelta))
cfgOptionSet(cfgOptDelta, cfgSourceParam, BOOL_TRUE_VAR);
// Resume a backup when possible
if (!backupResume(manifest, cipherPassBackup))
if (!backupResume(manifest, cipherSpecManifest))
{
manifestBackupLabelSet(
manifest,
@@ -255,10 +252,10 @@ cmdBackup(void)
}
// Save the manifest before processing starts
backupManifestSaveCopy(manifest, cipherPassBackup, false);
backupManifestSaveCopy(manifest, cipherSpecManifest, false);
// Process the backup manifest
backupProcess(backupData, manifest, cipherPassBackup);
backupProcess(backupData, manifest, cipherSpecManifest);
// Check that the clusters are alive and correctly configured after the backup
backupDbPing(backupData, true);
@@ -286,7 +283,7 @@ cmdBackup(void)
dbFree(backupData->dbPrimary);
// Check and copy WAL segments required to make the backup consistent
backupArchiveCheckCopy(backupData, manifest, cipherPassBackup);
backupArchiveCheckCopy(backupData, manifest, cipherSpecManifest);
// The primary protocol connection won't be used anymore so free it. This needs to happen after backupArchiveCheckCopy() so
// the backup lock is held on the remote which allows conditional archiving based on the backup lock. Any further access to

View File

@@ -3,11 +3,11 @@ Save a copy of the backup manifest during processing to preserve checksums for a
resume is disabled since an incremental copy will not be used in a future backup unless resume is enabled beforehand.
***********************************************************************************************************************************/
static void
backupManifestSaveCopy(Manifest *const manifest, const String *const cipherPassBackup, const bool final)
backupManifestSaveCopy(Manifest *const manifest, const CipherSpec *const cipherSpecManifest, const bool final)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(MANIFEST, manifest);
FUNCTION_TEST_PARAM(STRING, cipherPassBackup);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest);
FUNCTION_LOG_PARAM(BOOL, final);
FUNCTION_LOG_END();
@@ -25,8 +25,7 @@ backupManifestSaveCopy(Manifest *const manifest, const String *const cipherPassB
STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, strZ(manifestData(manifest)->backupLabel))));
// Add encryption filter if required
cipherBlockFilterGroupAdd(
ioWriteFilterGroup(write), cfgOptionStrId(cfgOptRepoCipherType), cipherModeEncrypt, cipherPassBackup);
cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherModeEncrypt, cipherSpecManifest);
// Save file
manifestSave(manifest, write);
@@ -41,12 +40,12 @@ backupManifestSaveCopy(Manifest *const manifest, const String *const cipherPassB
Check and copy WAL segments required to make the backup consistent
***********************************************************************************************************************************/
static void
backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manifest, const String *const cipherPassBackup)
backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manifest, const CipherSpec *const cipherSpecManifest)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(BACKUP_DATA, backupData);
FUNCTION_LOG_PARAM(MANIFEST, manifest);
FUNCTION_TEST_PARAM(STRING, cipherPassBackup);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest);
FUNCTION_LOG_END();
ASSERT(manifest != NULL);
@@ -67,7 +66,7 @@ backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manif
strZ(pgLsnToWalSegment(backupData->timeline, lsnStop, backupData->walSegmentSize)));
// Save the backup manifest before getting archive logs in case of failure
backupManifestSaveCopy(manifest, cipherPassBackup, false);
backupManifestSaveCopy(manifest, cipherSpecManifest, false);
// Use base path to set ownership and mode
const ManifestPath *const basePath = manifestPathFind(manifest, MANIFEST_TARGET_PGDATA_STR);
@@ -103,8 +102,7 @@ backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manif
// Decrypt with archive key if encrypted
cipherBlockFilterGroupAdd(
filterGroup, cfgOptionStrId(cfgOptRepoCipherType), cipherModeDecrypt,
infoArchiveCipherPass(backupData->archiveInfo));
filterGroup, cipherModeDecrypt, infoArchiveCipherSpec(backupData->archiveInfo));
// Compress/decompress if archive and backup do not have the same compression settings
if (archiveCompressType != backupCompressType)
@@ -121,7 +119,7 @@ backupArchiveCheckCopy(const BackupData *const backupData, Manifest *const manif
// Encrypt with backup key if encrypted
cipherBlockFilterGroupAdd(
filterGroup, cfgOptionStrId(cfgOptRepoCipherType), cipherModeEncrypt, manifestCipherSubPass(manifest));
filterGroup, cipherModeEncrypt, manifestCipherSpec(manifest));
// Add size filter last to calculate repo size
ioFilterGroupAdd(filterGroup, ioSizeNew());
@@ -188,7 +186,7 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest)
// -------------------------------------------------------------------------------------------------------------------------
manifestValidate(manifest, true);
backupManifestSaveCopy(manifest, infoPgCipherPass(infoBackupPg(infoBackup)), true);
backupManifestSaveCopy(manifest, infoBackupCipherSpec(infoBackup), true);
storageCopy(
storageNewReadP(
@@ -204,8 +202,7 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest)
storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabel)));
cipherBlockFilterGroupAdd(
ioReadFilterGroup(storageReadIo(manifestRead)), cfgOptionStrId(cfgOptRepoCipherType), cipherModeDecrypt,
infoPgCipherPass(infoBackupPg(infoBackup)));
ioReadFilterGroup(storageReadIo(manifestRead)), cipherModeDecrypt, infoBackupCipherSpec(infoBackup));
StorageWrite *const manifestWrite = storageNewWriteP(
storageRepoWrite(),
@@ -216,8 +213,7 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest)
ioFilterGroupAdd(ioWriteFilterGroup(storageWriteIo(manifestWrite)), compressFilterP(compressTypeGz, 9));
cipherBlockFilterGroupAdd(
ioWriteFilterGroup(storageWriteIo(manifestWrite)), cfgOptionStrId(cfgOptRepoCipherType), cipherModeEncrypt,
infoPgCipherPass(infoBackupPg(infoBackup)));
ioWriteFilterGroup(storageWriteIo(manifestWrite)), cipherModeEncrypt, infoBackupCipherSpec(infoBackup));
storageCopyP(manifestRead, manifestWrite);
@@ -233,19 +229,13 @@ backupComplete(InfoBackup *const infoBackup, Manifest *const manifest)
// Add manifest and save backup.info (infoBackupSaveFile() is responsible for proper syncing)
// -------------------------------------------------------------------------------------------------------------------------
infoBackupDataAdd(infoBackup, manifest);
infoBackupSaveFile(
infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType),
cfgOptionStrNull(cfgOptRepoCipherPass));
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMain());
// Save archive.info/copy so the timestamps will be updated to prevent lifecycle settings from removing the files early
// -------------------------------------------------------------------------------------------------------------------------
infoArchiveSaveFile(
infoArchiveLoadFile(
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType),
cfgOptionStrNull(cfgOptRepoCipherPass)),
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType),
cfgOptionStrNull(cfgOptRepoCipherPass));
infoArchiveLoadFile(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMain()), storageRepoWrite(),
INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMain());
}
MEM_CONTEXT_TEMP_END();

View File

@@ -221,12 +221,10 @@ backupFilePut(
}
// Add encryption filter if required
if (manifestCipherSubPass(manifest) != NULL)
if (cipherSpecType(manifestCipherSpec(manifest)) != cipherTypeNone)
{
ioFilterGroupAdd(
ioWriteFilterGroup(storageWriteIo(write)),
cipherBlockNewP(
cipherModeEncrypt, cfgOptionStrId(cfgOptRepoCipherType), BUFSTR(manifestCipherSubPass(manifest))));
ioWriteFilterGroup(storageWriteIo(write)), cipherBlockNewP(cipherModeEncrypt, manifestCipherSpec(manifest)));
repoChecksum = true;
}

View File

@@ -56,8 +56,8 @@ typedef struct BackupFileResult
static List *
backupFile(
const String *const repoFile, const uint64_t bundleId, const bool bundleRaw, const unsigned int blockIncrReference,
const CompressType repoFileCompressType, const int repoFileCompressLevel, const CipherType cipherType,
const String *const cipherPass, const String *const pgVersionForce, const PgPageSize pageSize, const List *const fileList)
const CompressType repoFileCompressType, const int repoFileCompressLevel, const CipherSpec *const cipherSpecBackup,
const String *const pgVersionForce, const PgPageSize pageSize, const List *const fileList)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, repoFile); // Repo file
@@ -66,15 +66,14 @@ backupFile(
FUNCTION_LOG_PARAM(UINT, blockIncrReference); // Block incremental reference to use in map
FUNCTION_LOG_PARAM(ENUM, repoFileCompressType); // Compress type for repo file
FUNCTION_LOG_PARAM(INT, repoFileCompressLevel); // Compression level for repo file
FUNCTION_LOG_PARAM(STRING_ID, cipherType); // Encryption type
FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to access the repo file if encrypted
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecBackup); // Cipher spec to encrypt the backup file
FUNCTION_LOG_PARAM(ENUM, pageSize); // Page size
FUNCTION_LOG_PARAM(STRING, pgVersionForce); // Force pg version
FUNCTION_LOG_PARAM(LIST, fileList); // List of files to backup
FUNCTION_LOG_END();
ASSERT(repoFile != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
ASSERT(cipherSpecBackup != NULL);
ASSERT(fileList != NULL && !lstEmpty(fileList));
ASSERT(pgPageSizeValid(pageSize));
@@ -217,7 +216,7 @@ backupFile(
}
// Are the files compressible during the copy?
const bool compressible = repoFileCompressType == compressTypeNone && cipherType == cipherTypeNone;
const bool compressible = repoFileCompressType == compressTypeNone && cipherSpecType(cipherSpecBackup) == cipherTypeNone;
// Copy files that need to be copied
StorageWrite *write = NULL;
@@ -276,9 +275,9 @@ backupFile(
// Encrypt filter
IoFilter *const encrypt =
cipherType != cipherTypeNone ?
cipherSpecType(cipherSpecBackup) != cipherTypeNone ?
cipherBlockNewP(
cipherModeEncrypt, cipherType, BUFSTR(cipherPass), .raw = bundleRaw || file->blockIncrSize != 0) :
cipherModeEncrypt, cipherSpecBackup, .raw = bundleRaw || file->blockIncrSize != 0) :
NULL;
// If block incremental then add the filter and pass compress/encrypt filters to it since each block is
@@ -293,11 +292,11 @@ backupFile(
blockMap = bufNew(0);
IoWrite *const blockMapWrite = ioBufferWriteNew(blockMap);
if (cipherType != cipherTypeNone)
if (cipherSpecType(cipherSpecBackup) != cipherTypeNone)
{
ioFilterGroupAdd(
ioWriteFilterGroup(blockMapWrite),
cipherBlockNewP(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), .raw = true));
cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = true));
}
ioWriteOpen(blockMapWrite);

View File

@@ -46,7 +46,7 @@ backupBuildIncrPrior(const InfoBackup *const infoBackup)
{
result = manifestLoadFile(
storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabelPrior)),
cfgOptionStrId(cfgOptRepoCipherType), infoPgCipherPass(infoBackupPg(infoBackup)));
infoBackupCipherSpec(infoBackup));
const ManifestData *const manifestPriorData = manifestData(result);
LOG_INFO_FMT(
@@ -144,7 +144,7 @@ backupBuildIncr(
manifestBuildIncr(manifest, manifestPrior, (BackupType)cfgOptionStrId(cfgOptType), archiveStart);
// Set the cipher subpass from prior manifest since we want a single subpass for the entire backup set
manifestCipherSubPassSet(manifest, manifestCipherSubPass(manifestPrior));
manifestCipherSpecSet(manifest, manifestCipherSpec(manifestPrior));
// Incremental was built
result = true;

View File

@@ -333,8 +333,7 @@ typedef struct BackupJobData
const String *const backupLabel; // Backup label (defines the backup path)
const bool backupStandby; // Backup from standby
RegExp *standbyExp; // Identify files that may be copied from the standby
const CipherType cipherType; // Cipher type
const String *const cipherSubPass; // Passphrase used to encrypt files in the backup
const CipherSpec *const cipherSpecBackup; // Cipher spec used to encrypt files in the backup
const PgPageSize pageSize; // Page size
const CompressType compressType; // Backup compression type
const int compressLevel; // Compress level if backup is compressed
@@ -685,8 +684,7 @@ backupJobCallback(void *const data, const unsigned int clientIdx)
pckWriteU32P(param, jobData->compressType);
pckWriteI32P(param, jobData->compressLevel);
pckWriteU64P(param, jobData->cipherSubPass == NULL ? cipherTypeNone : cipherTypeAes256Cbc);
pckWriteStrP(param, jobData->cipherSubPass);
cipherSpecPack(param, jobData->cipherSpecBackup);
pckWriteU32P(param, jobData->pageSize);
pckWriteStrP(param, cfgOptionStrNull(cfgOptPgVersionForce));
}
@@ -771,12 +769,12 @@ backupJobCallback(void *const data, const unsigned int clientIdx)
Process the backup manifest
***********************************************************************************************************************************/
static void
backupProcess(const BackupData *const backupData, Manifest *const manifest, const String *const cipherPassBackup)
backupProcess(const BackupData *const backupData, Manifest *const manifest, const CipherSpec *const cipherSpecManifest)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(BACKUP_DATA, backupData);
FUNCTION_LOG_PARAM(MANIFEST, manifest);
FUNCTION_TEST_PARAM(STRING, cipherPassBackup);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest);
FUNCTION_LOG_END();
ASSERT(manifest != NULL);
@@ -799,8 +797,7 @@ backupProcess(const BackupData *const backupData, Manifest *const manifest, cons
.backupStandby = backupData->dbStandby != NULL,
.compressType = compressTypeEnum(cfgOptionStrId(cfgOptCompressType)),
.compressLevel = cfgOptionInt(cfgOptCompressLevel),
.cipherType = cfgOptionStrId(cfgOptRepoCipherType),
.cipherSubPass = manifestCipherSubPass(manifest),
.cipherSpecBackup = manifestCipherSpec(manifest),
.pageSize = backupData->pageSize,
.delta = cfgOptionBool(cfgOptDelta),
.bundle = cfgOptionBool(cfgOptRepoBundle),
@@ -929,7 +926,7 @@ backupProcess(const BackupData *const backupData, Manifest *const manifest, cons
// Save the manifest periodically to preserve checksums for resume
if (sizeProgress - manifestSaveLast >= manifestSaveSize)
{
backupManifestSaveCopy(manifest, cipherPassBackup, false);
backupManifestSaveCopy(manifest, cipherSpecManifest, false);
manifestSaveLast = sizeProgress;
}

View File

@@ -115,8 +115,7 @@ backupFileProtocol(PackRead *const param)
const unsigned int blockIncrReference = (unsigned int)pckReadU64P(param);
const CompressType repoFileCompressType = (CompressType)pckReadU32P(param);
const int repoFileCompressLevel = pckReadI32P(param);
const CipherType cipherType = (CipherType)pckReadU64P(param);
const String *const cipherPass = pckReadStrP(param);
const CipherSpec *const cipherSpecBackup = cipherSpecNewPack(param);
const PgPageSize pageSize = pckReadU32P(param);
const String *const pgVersionForce = pckReadStrP(param);
@@ -163,7 +162,7 @@ backupFileProtocol(PackRead *const param)
// Backup file
const List *const resultList = backupFile(
repoFile, bundleId, bundleRaw, blockIncrReference, repoFileCompressType, repoFileCompressLevel, cipherType, cipherPass,
repoFile, bundleId, bundleRaw, blockIncrReference, repoFileCompressType, repoFileCompressLevel, cipherSpecBackup,
pgVersionForce, pageSize, fileList);
// Return result

View File

@@ -169,11 +169,11 @@ backupResumeClean(
// Helper to find a resumable backup
static const Manifest *
backupResumeFind(const Manifest *const manifest, const String *const cipherPassBackup)
backupResumeFind(const Manifest *const manifest, const CipherSpec *const cipherSpecManifest)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(MANIFEST, manifest);
FUNCTION_TEST_PARAM(STRING, cipherPassBackup);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest);
FUNCTION_LOG_END();
ASSERT(manifest != NULL);
@@ -217,8 +217,7 @@ backupResumeFind(const Manifest *const manifest, const String *const cipherPassB
{
TRY_BEGIN()
{
manifestResume = manifestLoadFile(
storageRepo(), manifestFile, cfgOptionStrId(cfgOptRepoCipherType), cipherPassBackup);
manifestResume = manifestLoadFile(storageRepo(), manifestFile, cipherSpecManifest);
}
CATCH_ANY()
{
@@ -296,11 +295,11 @@ backupResumeFind(const Manifest *const manifest, const String *const cipherPassB
}
static bool
backupResume(Manifest *const manifest, const String *const cipherPassBackup)
backupResume(Manifest *const manifest, const CipherSpec *const cipherSpecManifest)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(MANIFEST, manifest);
FUNCTION_TEST_PARAM(STRING, cipherPassBackup);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest);
FUNCTION_LOG_END();
ASSERT(manifest != NULL);
@@ -309,7 +308,7 @@ backupResume(Manifest *const manifest, const String *const cipherPassBackup)
MEM_CONTEXT_TEMP_BEGIN()
{
const Manifest *const manifestResume = backupResumeFind(manifest, cipherPassBackup);
const Manifest *const manifestResume = backupResumeFind(manifest, cipherSpecManifest);
// If a resumable backup was found set the label and cipher subpass
if (manifestResume)
@@ -325,7 +324,7 @@ backupResume(Manifest *const manifest, const String *const cipherPassBackup)
strZ(manifestData(manifest)->backupLabel));
// Copy cipher subpass since it was used to encrypt the resumable files
manifestCipherSubPassSet(manifest, manifestCipherSubPass(manifestResume));
manifestCipherSpecSet(manifest, manifestCipherSpec(manifestResume));
// Clean resumed backup
const String *const backupPath = strNewFmt(STORAGE_REPO_BACKUP "/%s", strZ(manifestData(manifest)->backupLabel));

View File

@@ -92,7 +92,7 @@ checkStandby(const DbGetResult dbGroup, const unsigned int pgPathDefinedTotal)
// Check that the backup and archive info files exist and are valid for the current database of the stanza
checkStanzaInfoPg(
storageRepo, dbPgControl(dbGroup.standby).version, dbPgControl(dbGroup.standby).systemId,
cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
cfgCipherSpecMainIdx(repoIdx));
}
LOG_INFO("switch wal not performed because this is a standby");
@@ -137,12 +137,11 @@ checkPrimary(const DbGetResult dbGroup)
// Check that the backup and archive info files exist and are valid for the current database of the stanza
checkStanzaInfoPg(
storageRepo, dbPgControl(dbGroup.primary).version, dbPgControl(dbGroup.primary).systemId,
cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
cfgCipherSpecMainIdx(repoIdx));
// Attempt to load the archive info file and retrieve the archiveId
const InfoArchive *const archiveInfo = infoArchiveLoadFile(
storageRepo, INFO_ARCHIVE_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
storageRepo, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
repoArchiveId[repoIdx] = infoArchiveId(archiveInfo);
}

View File

@@ -124,15 +124,13 @@ checkStanzaInfo(const InfoPgData *const archiveInfo, const InfoPgData *const bac
/**********************************************************************************************************************************/
FN_EXTERN void
checkStanzaInfoPg(
const Storage *const storage, const unsigned int pgVersion, const uint64_t pgSystemId, const CipherType cipherType,
const String *const cipherPass)
const Storage *const storage, const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *const cipherSpecMain)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STORAGE, storage);
FUNCTION_TEST_PARAM(UINT, pgVersion);
FUNCTION_TEST_PARAM(UINT64, pgSystemId);
FUNCTION_TEST_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_TEST_PARAM(CIPHER_SPEC, cipherSpecMain);
FUNCTION_TEST_END();
ASSERT(storage != NULL);
@@ -140,9 +138,9 @@ checkStanzaInfoPg(
MEM_CONTEXT_TEMP_BEGIN()
{
// Check that the backup and archive info files exist
const InfoArchive *const infoArchive = infoArchiveLoadFile(storage, INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass);
const InfoArchive *const infoArchive = infoArchiveLoadFile(storage, INFO_ARCHIVE_PATH_FILE_STR, cipherSpecMain);
const InfoPgData archiveInfoPg = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
const InfoBackup *const infoBackup = infoBackupLoadFile(storage, INFO_BACKUP_PATH_FILE_STR, cipherType, cipherPass);
const InfoBackup *const infoBackup = infoBackupLoadFile(storage, INFO_BACKUP_PATH_FILE_STR, cipherSpecMain);
const InfoPgData backupInfoPg = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
// Check that the info files pg data match each other

View File

@@ -4,6 +4,7 @@ Check Command Common
#ifndef COMMAND_CHECK_COMMON_H
#define COMMAND_CHECK_COMMON_H
#include "common/crypto/spec.h"
#include "common/type/string.h"
#include "db/db.h"
#include "info/infoPg.h"
@@ -19,7 +20,6 @@ FN_EXTERN void checkStanzaInfo(const InfoPgData *archiveInfo, const InfoPgData *
// Load and validate the database data of the info files against each other and the current database
FN_EXTERN void checkStanzaInfoPg(
const Storage *storage, const unsigned int pgVersion, const uint64_t pgSystemId, CipherType cipherType,
const String *cipherPass);
const Storage *storage, const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *cipherSpecMain);
#endif

View File

@@ -585,8 +585,7 @@ removeExpiredArchive(const InfoBackup *const infoBackup, const bool timeBasedFul
{
// Attempt to load the archive info file
const InfoArchive *const infoArchive = infoArchiveLoadFile(
storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
storageRepoIdx(repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
const InfoPg *const infoArchivePgData = infoArchivePg(infoArchive);
// Get a list of archive directories (e.g. 9.6-1, 10-2, etc) sorted by the db-id (number after the dash).
@@ -897,8 +896,7 @@ removeExpiredBackup(const InfoBackup *const infoBackup, const String *const adho
if (adhocBackupLabel != NULL && strBeginsWith(strLstGet(backupList, 0), strSubN(adhocBackupLabel, 0, 16)))
{
const Manifest *const manifestResume = manifestLoadFile(
storageRepoIdx(repoIdx), manifestFileName, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
infoPgCipherPass(infoBackupPg(infoBackup)));
storageRepoIdx(repoIdx), manifestFileName, infoBackupCipherSpec(infoBackup));
// If the ancestor of the resumable backup no longer exists in backup.info then it can be removed
if (!infoBackupLabelExists(infoBackup, manifestData(manifestResume)->backupLabelPrior))
@@ -1096,9 +1094,7 @@ cmdExpire(void)
TRY_BEGIN()
{
// Load backup.info for this repo
infoBackup = infoBackupLoadFileReconstruct(
storageRepo, INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
infoBackup = infoBackupLoadFileReconstruct(storageRepo, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
// When expire oldest requested, expire the oldest full backup by lowering retention for this execution
if (expireOldest)
@@ -1180,8 +1176,7 @@ cmdExpire(void)
if (!cfgOptionValid(cfgOptDryRun) || !cfgOptionBool(cfgOptDryRun))
{
infoBackupSaveFile(
infoBackup, storageRepoIdxWrite(repoIdx), INFO_BACKUP_PATH_FILE_STR,
cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
infoBackup, storageRepoIdxWrite(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
}
// Remove all files on disk that are now expired

View File

@@ -132,7 +132,6 @@ typedef struct InfoRepoData
{
unsigned int key; // User-defined repo key
CipherType cipher; // Encryption type
const String *cipherPass; // Passphrase if the repo is encrypted (else NULL)
int stanzaStatus; // Status code of the stanza on this repo
unsigned int backupIdx; // Index of the next backup that may be a candidate for sorting
InfoBackup *backupInfo; // Contents of the backup.info file of the stanza on this repo
@@ -1478,7 +1477,7 @@ infoUpdateStanza(
// Attempt to load the backup info file
stanzaRepo->repoList[repoIdx].backupInfo = infoBackupLoadFile(
storage, strNewFmt(STORAGE_PATH_BACKUP "/%s/%s", strZ(stanzaRepo->name), INFO_BACKUP_FILE),
stanzaRepo->repoList[repoIdx].cipher, stanzaRepo->repoList[repoIdx].cipherPass);
cfgCipherSpecMainIdx(repoIdx));
}
CATCH(FileMissingError)
{
@@ -1502,15 +1501,14 @@ infoUpdateStanza(
{
stanzaRepo->repoList[repoIdx].archiveInfo = infoArchiveLoadFile(
storage, strNewFmt(STORAGE_PATH_ARCHIVE "/%s/%s", strZ(stanzaRepo->name), INFO_ARCHIVE_FILE),
stanzaRepo->repoList[repoIdx].cipher, stanzaRepo->repoList[repoIdx].cipherPass);
cfgCipherSpecMainIdx(repoIdx));
// If a specific backup exists on this repo then attempt to load the manifest
if (backupLabel != NULL)
{
stanzaRepo->repoList[repoIdx].manifest = manifestLoadFile(
storage, strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabel)),
stanzaRepo->repoList[repoIdx].cipher,
infoPgCipherPass(infoBackupPg(stanzaRepo->repoList[repoIdx].backupInfo)));
infoBackupCipherSpec(stanzaRepo->repoList[repoIdx].backupInfo));
}
}
}
@@ -1600,7 +1598,6 @@ infoRender(void)
{
.key = cfgOptionGroupIdxToKey(cfgOptGrpRepo, repoIdx),
.cipher = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
.cipherPass = cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx),
.error = NULL,
};
@@ -1673,7 +1670,6 @@ infoRender(void)
{
.key = cfgOptionGroupIdxToKey(cfgOptGrpRepo, repoListIdx),
.cipher = cfgOptionIdxStrId(cfgOptRepoCipherType, repoListIdx),
.cipherPass = cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoListIdx),
.error = NULL,
};
}

View File

@@ -231,12 +231,11 @@ cmdManifestBlockDeltaRender(const Manifest *const manifest, const ManifestFile *
.offset = file->bundleOffset + file->sizeRepo - file->blockIncrMapSize,
.limit = VARUINT64(file->blockIncrMapSize));
if (manifestCipherSubPass(manifest) != NULL)
if (cipherSpecType(manifestCipherSpec(manifest)) != cipherTypeNone)
{
ioFilterGroupAdd(
ioReadFilterGroup(storageReadIo(read)),
cipherBlockNewP(
cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(manifestCipherSubPass(manifest)), .raw = true));
cipherBlockNewP(cipherModeDecrypt, manifestCipherSpec(manifest), .raw = true));
}
ioReadOpen(storageReadIo(read));
@@ -442,16 +441,12 @@ cmdManifestRender(void)
storageRepo();
// Load backup.info and cipher
const InfoBackup *const infoBackup = infoBackupLoadFile(
storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgOptionStrId(cfgOptRepoCipherType),
cfgOptionStrNull(cfgOptRepoCipherPass));
const String *const cipherPass = infoPgCipherPass(infoBackupPg(infoBackup));
const CipherType cipherType = cipherPass == NULL ? cipherTypeNone : cipherTypeAes256Cbc;
const InfoBackup *const infoBackup = infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMain());
// Load manifest
const Manifest *const manifest = manifestLoadFile(
storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(cfgOptionStr(cfgOptSet))),
cipherType, cipherPass);
infoBackupCipherSpec(infoBackup));
// Manifest info
const ManifestData *const data = manifestData(manifest);

View File

@@ -56,18 +56,18 @@ storageGetProcess(IoWrite *const destination)
{
// Determine the passphrase using the following pattern:
//
// REPO / (repo passphrase)
// / archive / (repo passphrase)
// REPO / (main passphrase)
// / archive / (main passphrase)
// / archive / stanza / (archive passphrase)
// / backup / (repo passphrase)
// / backup / stanza / (backup passphrase)
// / backup / stanza / set / (manifest passphrase)
// / backup / stanza / backup.history / (backup passphrase)
// / backup / (main passphrase)
// / backup / stanza / (manifest passphrase)
// / backup / stanza / set / (backup passphrase)
// / backup / stanza / backup.history / (manifest passphrase)
//
// Nothing should be stored at the top level of the repo except the backup/archive paths. The backup/archive paths
// should contain only stanza paths.
// -----------------------------------------------------------------------------------------------------------------
const String *cipherPass = NULL;
const CipherSpec *cipherSpec = NULL;
const StringList *const filePathSplitLst = strLstNewSplit(file, FSLASH_STR);
// At a minimum the path must contain archive/backup, a stanza, and a file
@@ -86,32 +86,32 @@ storageGetProcess(IoWrite *const destination)
// Archive path
if (strEq(strLstGet(filePathSplitLst, 0), STORAGE_PATH_ARCHIVE_STR))
{
cipherPass = cfgOptionStr(cfgOptRepoCipherPass);
cipherSpec = cfgCipherSpecMain();
// Find the archive passphrase
if (!strEndsWithZ(file, INFO_ARCHIVE_FILE) && !strEndsWithZ(file, INFO_ARCHIVE_FILE INFO_COPY_EXT))
{
const InfoArchive *const info = infoArchiveLoadFile(
storageRepo(), strNewFmt(STORAGE_PATH_ARCHIVE "/%s/%s", strZ(stanza), INFO_ARCHIVE_FILE),
repoCipherType, cipherPass);
cipherPass = infoArchiveCipherPass(info);
cfgCipherSpecMain());
cipherSpec = infoArchiveCipherSpec(info);
}
}
// Backup path
if (strEq(strLstGet(filePathSplitLst, 0), STORAGE_PATH_BACKUP_STR))
{
cipherPass = cfgOptionStr(cfgOptRepoCipherPass);
cipherSpec = cfgCipherSpecMain();
if (!strEndsWithZ(file, INFO_BACKUP_FILE) && !strEndsWithZ(file, INFO_BACKUP_FILE INFO_COPY_EXT))
{
// Find the backup passphrase
// Find the manifest passphrase
const InfoBackup *const info = infoBackupLoadFile(
storageRepo(), strNewFmt(STORAGE_PATH_BACKUP "/%s/%s", strZ(stanza), INFO_BACKUP_FILE),
repoCipherType, cipherPass);
cipherPass = infoBackupCipherPass(info);
cfgCipherSpecMain());
const CipherSpec *const cipherSpecManifest = infoBackupCipherSpec(info);
// Find the manifest passphrase
// Find the backup passphrase if not a manifest
if (!strEq(strLstGet(filePathSplitLst, 2), STRDEF(BACKUP_PATH_HISTORY)) &&
!strEndsWithZ(file, BACKUP_MANIFEST_FILE) &&
!strEndsWithZ(file, BACKUP_MANIFEST_FILE INFO_COPY_EXT))
@@ -121,19 +121,24 @@ storageGetProcess(IoWrite *const destination)
strNewFmt(
STORAGE_PATH_BACKUP "/%s/%s/%s", strZ(stanza), strZ(strLstGet(filePathSplitLst, 2)),
BACKUP_MANIFEST_FILE),
repoCipherType, cipherPass);
cipherPass = manifestCipherSubPass(manifest);
cipherSpecManifest);
cipherSpec = manifestCipherSpec(manifest);
}
// Else use the manifest passphrase
else
cipherSpec = cipherSpecManifest;
}
}
}
// Error when unable to determine cipher passphrase
if (cipherPass == NULL)
if (cipherSpec == NULL)
THROW_FMT(OptionInvalidValueError, "unable to determine cipher passphrase for '%s'", strZ(file));
ASSERT(cipherSpecType(cipherSpec) != cipherTypeNone);
// Add encryption filter
cipherBlockFilterGroupAdd(ioReadFilterGroup(source), repoCipherType, cipherModeDecrypt, cipherPass);
cipherBlockFilterGroupAdd(ioReadFilterGroup(source), cipherModeDecrypt, cipherSpec);
}
}

View File

@@ -32,8 +32,7 @@ struct BlockDelta
BlockDeltaPub pub; // Publicly accessible variables
size_t blockSize; // Block size
size_t checksumSize; // Checksum size
CipherType cipherType; // Cipher type
String *cipherPass; // Cipher passphrase
const CipherSpec *cipherSpecBackup; // Cipher spec
CompressType compressType; // Compress type
const BlockDeltaSuperBlock *superBlockData; // Current super block data
@@ -57,21 +56,20 @@ typedef struct BlockDeltaReference
FN_EXTERN BlockDelta *
blockDeltaNew(
const BlockMap *const blockMap, const size_t blockSize, const size_t checksumSize, const Buffer *const blockChecksum,
const CipherType cipherType, const String *const cipherPass, const CompressType compressType)
const CipherSpec *const cipherSpecBackup, const CompressType compressType)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(BLOCK_MAP, blockMap);
FUNCTION_TEST_PARAM(SIZE, blockSize);
FUNCTION_TEST_PARAM(SIZE, checksumSize);
FUNCTION_TEST_PARAM(BUFFER, blockChecksum);
FUNCTION_TEST_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_TEST_PARAM(CIPHER_SPEC, cipherSpecBackup);
FUNCTION_TEST_PARAM(ENUM, compressType);
FUNCTION_TEST_END();
ASSERT(blockMap != NULL);
ASSERT(blockSize > 0);
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
ASSERT(cipherSpecBackup != NULL);
OBJ_NEW_BEGIN(BlockDelta, .childQty = MEM_CONTEXT_QTY_MAX)
{
@@ -83,8 +81,7 @@ blockDeltaNew(
},
.blockSize = blockSize,
.checksumSize = checksumSize,
.cipherType = cipherType,
.cipherPass = strDup(cipherPass),
.cipherSpecBackup = cipherSpecDup(cipherSpecBackup),
.compressType = compressType,
.write =
{
@@ -237,11 +234,10 @@ blockDeltaNext(BlockDelta *const this, const BlockDeltaRead *const readDelta, Io
}
MEM_CONTEXT_OBJ_END();
if (this->cipherType != cipherTypeNone)
if (cipherSpecType(this->cipherSpecBackup) != cipherTypeNone)
{
ioFilterGroupAdd(
ioReadFilterGroup(this->limitRead),
cipherBlockNewP(cipherModeDecrypt, this->cipherType, BUFSTR(this->cipherPass), .raw = true));
ioReadFilterGroup(this->limitRead), cipherBlockNewP(cipherModeDecrypt, this->cipherSpecBackup, .raw = true));
}
if (this->compressType != compressTypeNone)

View File

@@ -9,7 +9,7 @@ optional because the file to restore may not exist so all the blocks will need t
#include "command/backup/blockMap.h"
#include "common/compress/helper.h"
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
/***********************************************************************************************************************************
Object type
@@ -37,8 +37,8 @@ typedef struct BlockDeltaWrite
Constructors
***********************************************************************************************************************************/
FN_EXTERN BlockDelta *blockDeltaNew(
const BlockMap *blockMap, size_t blockSize, size_t checksumSize, const Buffer *blockChecksum, CipherType cipherType,
const String *cipherPass, const CompressType compressType);
const BlockMap *blockMap, size_t blockSize, size_t checksumSize, const Buffer *blockChecksum,
const CipherSpec *cipherSpecBackup, const CompressType compressType);
/***********************************************************************************************************************************
Functions

View File

@@ -30,7 +30,7 @@ typedef struct RestoreFileResult
static List *
restoreFile(
const String *const repoFile, const unsigned int repoIdx, const CompressType repoFileCompressType, const time_t copyTimeBegin,
const bool delta, const bool deltaForce, const bool bundleRaw, const String *const cipherPass,
const bool delta, const bool deltaForce, const bool bundleRaw, const CipherSpec *const cipherSpecBackup,
const StringList *const referenceList, List *const fileList)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
@@ -41,7 +41,7 @@ restoreFile(
FUNCTION_LOG_PARAM(BOOL, delta);
FUNCTION_LOG_PARAM(BOOL, deltaForce);
FUNCTION_LOG_PARAM(BOOL, bundleRaw);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecBackup);
FUNCTION_LOG_PARAM(STRING_LIST, referenceList); // List of references (for block incremental)
FUNCTION_LOG_PARAM(LIST, fileList); // List of files to restore
FUNCTION_LOG_END();
@@ -220,7 +220,9 @@ restoreFile(
if (fileResult->result == restoreResultCopy)
{
storageReadMultiAddP(
repoFileRead, repoFile, .compressible = repoFileCompressType == compressTypeNone && cipherPass == NULL,
repoFileRead, repoFile,
.compressible =
repoFileCompressType == compressTypeNone && cipherSpecType(cipherSpecBackup) == cipherTypeNone,
.offset = file->offset, .limit = file->limit);
}
}
@@ -259,11 +261,10 @@ restoreFile(
// blocks need to be fetched from the repository. If we got here there must be at least one block to fetch.
IoRead *const blockMapRead = ioLimitReadNew(storageReadMultiIo(repoFileRead), varUInt64(file->limit));
if (cipherPass != NULL)
if (cipherSpecType(cipherSpecBackup) != cipherTypeNone)
{
ioFilterGroupAdd(
ioReadFilterGroup(blockMapRead),
cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(cipherPass), .raw = true));
ioReadFilterGroup(blockMapRead), cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = true));
}
ioReadOpen(blockMapRead);
@@ -278,8 +279,8 @@ restoreFile(
// Apply delta to file
BlockDelta *const blockDelta = blockDeltaNew(
blockMap, file->blockIncrSize, file->blockIncrChecksumSize, file->blockChecksum,
cipherPass == NULL ? cipherTypeNone : cipherTypeAes256Cbc, cipherPass, repoFileCompressType);
blockMap, file->blockIncrSize, file->blockIncrChecksumSize, file->blockChecksum, cipherSpecBackup,
repoFileCompressType);
for (unsigned int readIdx = 0; readIdx < blockDeltaReadSize(blockDelta); readIdx++)
{
@@ -333,11 +334,9 @@ restoreFile(
IoFilterGroup *const filterGroup = ioWriteFilterGroup(storageWriteIo(pgFileWrite));
// Add decryption filter
if (cipherPass != NULL)
if (cipherSpecType(cipherSpecBackup) != cipherTypeNone)
{
ioFilterGroupAdd(
filterGroup,
cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(cipherPass), .raw = bundleRaw));
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = bundleRaw));
}
// Add decompression filter

View File

@@ -336,7 +336,7 @@ typedef struct RestoreJobData
Manifest *manifest; // Backup manifest
List *queueList; // List of processing queues
RegExp *zeroExp; // Identify files that should be sparse zeroed
const String *cipherSubPass; // Passphrase used to decrypt files in the backup
const CipherSpec *cipherSpecBackup; // Cipher spec used to decrypt files in the backup
const String *rootReplaceUser; // User to replace invalid users when root
const String *rootReplaceGroup; // Group to replace invalid group when root
} RestoreJobData;
@@ -429,7 +429,7 @@ restoreJobCallback(void *const data, const unsigned int clientIdx)
pckWriteBoolP(param, cfgOptionBool(cfgOptDelta));
pckWriteBoolP(param, cfgOptionBool(cfgOptDelta) && cfgOptionBool(cfgOptForce));
pckWriteBoolP(param, file.bundleId != 0 && manifestData(jobData->manifest)->bundleRaw);
pckWriteStrP(param, jobData->cipherSubPass);
cipherSpecPack(param, jobData->cipherSpecBackup);
pckWriteStrLstP(param, manifestReferenceList(jobData->manifest));
fileAdded = true;

View File

@@ -46,7 +46,7 @@ restoreFileProtocol(PackRead *const param)
const bool delta = pckReadBoolP(param);
const bool deltaForce = pckReadBoolP(param);
const bool bundleRaw = pckReadBoolP(param);
const String *const cipherPass = pckReadStrP(param);
const CipherSpec *const cipherSpecBackup = cipherSpecNewPack(param);
const StringList *const referenceList = pckReadStrLstP(param);
// Build the file list
@@ -85,7 +85,7 @@ restoreFileProtocol(PackRead *const param)
// Restore files
const List *const resultList = restoreFile(
repoFile, repoIdx, repoFileCompressType, copyTimeBegin, delta, deltaForce, bundleRaw, cipherPass, referenceList,
repoFile, repoIdx, repoFileCompressType, copyTimeBegin, delta, deltaForce, bundleRaw, cipherSpecBackup, referenceList,
fileList);
// Return result

View File

@@ -11,6 +11,7 @@ Restore Command
#include "command/restore/timeline.h"
#include "common/regExp.h"
#include "common/user.h"
#include "config/config.h"
#include "config/exec.h"
#include "info/infoArchive.h"
#include "info/infoBackup.h"
@@ -58,24 +59,21 @@ cmdRestore(void)
jobData.manifest = manifestLoadFile(
storageRepoIdx(backupData.repoIdx),
strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupData.backupSet)), backupData.repoCipherType,
backupData.backupCipherPass);
strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupData.backupSet)), backupData.cipherSpecManifest);
// Verify that the selected timeline is valid for the backup -- including current and latest timelines
if (manifestData(jobData.manifest)->backupOptionOnline)
{
const ManifestData *const data = manifestData(jobData.manifest);
const InfoArchive *const archiveInfo = infoArchiveLoadFile(
storageRepoIdx(backupData.repoIdx), INFO_ARCHIVE_PATH_FILE_STR,
cfgOptionIdxStrId(cfgOptRepoCipherType, backupData.repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, backupData.repoIdx));
storageRepoIdx(backupData.repoIdx), INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(backupData.repoIdx));
timelineVerify(
storageRepoIdx(backupData.repoIdx),
strNewFmt("%s-%u", strZ(pgVersionToStr(data->pgVersion)), data->pgId), data->pgVersion,
cvtZToUIntBase(strZ(strSubN(data->archiveStart, 0, 8)), 16), pgLsnFromStr(data->lsnStart),
cfgOptionStrNull(cfgOptTargetTimeline), cfgOptionSeq(cfgOptType),
cfgOptionIdxStrId(cfgOptRepoCipherType, backupData.repoIdx), infoArchiveCipherPass(archiveInfo));
infoArchiveCipherSpec(archiveInfo));
}
// Remotes (if any) are no longer needed since the rest of the repository reads will be done by the local processes
@@ -91,8 +89,8 @@ cmdRestore(void)
// Validate manifest. Don't use strict mode because we'd rather ignore problems that won't affect a restore.
manifestValidate(jobData.manifest, false);
// Get the cipher subpass used to decrypt files in the backup
jobData.cipherSubPass = manifestCipherSubPass(jobData.manifest);
// Get the cipher spec used to decrypt files in the backup
jobData.cipherSpecBackup = manifestCipherSpec(jobData.manifest);
// Validate the manifest
restoreManifestValidate(jobData.manifest, backupData.backupSet);

View File

@@ -4,8 +4,7 @@ Get the backup set to restore
typedef struct RestoreBackupData
{
unsigned int repoIdx; // Internal repo index
CipherType repoCipherType; // Repo encryption type (0 = none)
const String *backupCipherPass; // Passphrase of backup files if repo is encrypted (else NULL)
const CipherSpec *cipherSpecManifest; // Cipher spec to open the manifest, none when not encrypted
const String *backupSet; // Backup set to restore
} RestoreBackupData;
@@ -16,7 +15,7 @@ typedef struct RestoreBackupData
// Helper function for restoreBackupSet
static RestoreBackupData
restoreBackupData(const String *const backupLabel, const unsigned int repoIdx, const String *const backupCipherPass)
restoreBackupData(const String *const backupLabel, const unsigned int repoIdx, const CipherSpec *const cipherSpecManifest)
{
ASSERT(backupLabel != NULL);
@@ -26,8 +25,7 @@ restoreBackupData(const String *const backupLabel, const unsigned int repoIdx, c
{
restoreBackup.backupSet = strDup(backupLabel);
restoreBackup.repoIdx = repoIdx;
restoreBackup.repoCipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx);
restoreBackup.backupCipherPass = strDup(backupCipherPass);
restoreBackup.cipherSpecManifest = cipherSpecDup(cipherSpecManifest);
}
MEM_CONTEXT_PRIOR_END();
@@ -103,9 +101,7 @@ restoreBackupSet(void)
// Attempt to load backup.info
TRY_BEGIN()
{
infoBackup = infoBackupLoadFile(
storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
infoBackup = infoBackupLoadFile(storageRepoIdx(repoIdx), INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
}
CATCH_ANY()
{
@@ -160,7 +156,7 @@ restoreBackupSet(void)
{
found = true;
result = restoreBackupData(backupData.backupLabel, repoIdx, infoPgCipherPass(infoBackupPg(infoBackup)));
result = restoreBackupData(backupData.backupLabel, repoIdx, infoBackupCipherSpec(infoBackup));
break;
}
}
@@ -187,7 +183,7 @@ restoreBackupSet(void)
strZ(latestBackup.backupLabel));
}
result = restoreBackupData(latestBackup.backupLabel, repoIdx, infoPgCipherPass(infoBackupPg(infoBackup)));
result = restoreBackupData(latestBackup.backupLabel, repoIdx, infoBackupCipherSpec(infoBackup));
break;
}
}
@@ -198,7 +194,7 @@ restoreBackupSet(void)
{
if (strEq(infoBackupData(infoBackup, backupIdx).backupLabel, backupSetRequested))
{
result = restoreBackupData(backupSetRequested, repoIdx, infoPgCipherPass(infoBackupPg(infoBackup)));
result = restoreBackupData(backupSetRequested, repoIdx, infoBackupCipherSpec(infoBackup));
break;
}
}

View File

@@ -78,15 +78,14 @@ Load history file
***********************************************************************************************************************************/
static List *
historyLoad(
const Storage *const storageRepo, const String *const archiveId, const unsigned int timeline, const CipherType cipherType,
const String *const cipherPass)
const Storage *const storageRepo, const String *const archiveId, const unsigned int timeline,
const CipherSpec *const cipherSpecArchive)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storageRepo);
FUNCTION_LOG_PARAM(STRING, archiveId);
FUNCTION_LOG_PARAM(UINT, timeline);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_LOG_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecArchive);
FUNCTION_LOG_END();
List *result;
@@ -95,7 +94,7 @@ historyLoad(
{
const String *const historyFile = strNewFmt(STORAGE_REPO_ARCHIVE "/%s/%08X.history", strZ(archiveId), timeline);
StorageRead *const storageRead = storageNewReadP(storageRepo, historyFile);
cipherBlockFilterGroupAdd(ioReadFilterGroup(storageReadIo(storageRead)), cipherType, cipherModeDecrypt, cipherPass);
cipherBlockFilterGroupAdd(ioReadFilterGroup(storageReadIo(storageRead)), cipherModeDecrypt, cipherSpecArchive);
const Buffer *const history = storageGetP(storageRead);
TRY_BEGIN()
@@ -159,7 +158,7 @@ FN_EXTERN void
timelineVerify(
const Storage *const storageRepo, const String *const archiveId, const unsigned int pgVersion,
const unsigned int timelineBackup, const uint64_t lsnBackup, const String *timelineTargetStr, const unsigned int recoveryType,
const CipherType cipherType, const String *const cipherPass)
const CipherSpec *const cipherSpecArchive)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storageRepo);
@@ -169,8 +168,7 @@ timelineVerify(
FUNCTION_LOG_PARAM(UINT64, lsnBackup);
FUNCTION_LOG_PARAM(STRING, timelineTargetStr);
FUNCTION_LOG_PARAM(UINT, recoveryType);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_LOG_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecArchive);
FUNCTION_LOG_END();
ASSERT(storageRepo != NULL);
@@ -223,7 +221,7 @@ timelineVerify(
{
// Search through the history for the target timeline to make sure it includes the backup timeline. This follows
// the logic in PostgreSQL's readTimeLineHistory() and tliOfPointInHistory() but is a bit simplified for our usage.
const List *const historyList = historyLoad(storageRepo, archiveId, timelineTarget, cipherType, cipherPass);
const List *const historyList = historyLoad(storageRepo, archiveId, timelineTarget, cipherSpecArchive);
unsigned int timelineFound = 0;
for (unsigned int historyIdx = 0; historyIdx < lstSize(historyList); historyIdx++)

View File

@@ -4,7 +4,7 @@ Timeline Management
#ifndef COMMAND_RESTORE_TIMELINE_H
#define COMMAND_RESTORE_TIMELINE_H
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
#include "storage/storage.h"
/***********************************************************************************************************************************
@@ -12,8 +12,7 @@ Functions
***********************************************************************************************************************************/
// Verify that target timeline is valid for a backup
FN_EXTERN void timelineVerify(
const Storage *storageRepo, const String *archiveId, unsigned int pgVersion, unsigned int timelineBackup,
uint64_t lsnBackup, const String *timelineTargetStr, unsigned int recoveryType, CipherType cipherType,
const String *cipherPass);
const Storage *storageRepo, const String *archiveId, unsigned int pgVersion, unsigned int timelineBackup, uint64_t lsnBackup,
const String *timelineTargetStr, unsigned int recoveryType, const CipherSpec *cipherSpecArchive);
#endif

View File

@@ -15,24 +15,32 @@ Stanza Commands Handler
#include "storage/helper.h"
/**********************************************************************************************************************************/
FN_EXTERN String *
cipherPassGen(const CipherType cipherType)
FN_EXTERN CipherSpec *
cipherSpecGen(const CipherType cipherType)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_END();
String *result = NULL;
CipherSpec *result;
if (cipherType != cipherTypeNone)
if (cipherType == cipherTypeNone)
result = cipherSpecNewNone();
else
{
uint8_t buffer[48]; // 48 is the amount of entropy needed to get a 64 base key
cryptoRandomBytes(buffer, sizeof(buffer));
MEM_CONTEXT_TEMP_BEGIN()
{
uint8_t buffer[48]; // 48 is the amount of entropy needed to get a 64 base key
cryptoRandomBytes(buffer, sizeof(buffer));
result = strNewEncode(encodingBase64, BUF(buffer, sizeof(buffer)));
// The pass is the encoded text rather than the bytes it encodes, so it is stored and derived from as that text
result = cipherSpecNew(cipherType, BUFSTR(strNewEncode(encodingBase64, BUF(buffer, sizeof(buffer)))));
cipherSpecMove(result, memContextPrior());
}
MEM_CONTEXT_TEMP_END();
}
FUNCTION_TEST_RETURN(STRING, result);
FUNCTION_TEST_RETURN(CIPHER_SPEC, result);
}
/**********************************************************************************************************************************/

View File

@@ -10,8 +10,8 @@ Stanza Commands Handler
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
// Generate a cipher
FN_EXTERN String *cipherPassGen(CipherType cipherType);
// Generate cipher spec with a new pass, none when the type is none
FN_EXTERN CipherSpec *cipherSpecGen(CipherType cipherType);
// Validate and return database information
FN_EXTERN PgControl pgValidate(void);

View File

@@ -75,33 +75,27 @@ cmdStanzaCreate(void)
}
// If the repo is encrypted, generate a cipher passphrase for encrypting subsequent archive files
const String *cipherPassSub = cipherPassGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx));
const CipherSpec *const cipherSpecArchive = cipherSpecGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx));
// Create and save archive info
infoArchive = infoArchiveNew(pgControl.version, pgControl.systemId, cipherPassSub);
infoArchive = infoArchiveNew(pgControl.version, pgControl.systemId, cipherSpecArchive);
infoArchiveSaveFile(
infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR,
cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
infoArchiveSaveFile(infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
// If the repo is encrypted, generate a cipher passphrase for encrypting subsequent backup files
cipherPassSub = cipherPassGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx));
// If the repo is encrypted, generate a cipher passphrase for encrypting subsequent manifests
const CipherSpec *const cipherSpecManifest = cipherSpecGen(cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx));
// Create and save backup info
infoBackup = infoBackupNew(pgControl.version, pgControl.systemId, pgControl.catalogVersion, cipherPassSub);
infoBackup = infoBackupNew(pgControl.version, pgControl.systemId, pgControl.catalogVersion, cipherSpecManifest);
infoBackupSaveFile(
infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR,
cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
infoBackupSaveFile(infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
}
// Else if at least one archive and one backup info file exists, then ensure both are valid
else if ((archiveInfoFileExists || archiveInfoFileCopyExists) && (backupInfoFileExists || backupInfoFileCopyExists))
{
// Error if there is a mismatch between the archive and backup info files or the database version/system Id matches
// current database
checkStanzaInfoPg(
storageRepoReadStanza, pgControl.version, pgControl.systemId,
cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
checkStanzaInfoPg(storageRepoReadStanza, pgControl.version, pgControl.systemId, cfgCipherSpecMainIdx(repoIdx));
// The files are valid - upgrade
const String *sourceFile = NULL;

View File

@@ -51,13 +51,11 @@ cmdStanzaUpgrade(void)
// Load the info files (errors if missing)
InfoArchive *const infoArchive = infoArchiveLoadFile(
storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
InfoPgData archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
InfoBackup *const infoBackup = infoBackupLoadFile(
storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
InfoPgData backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
// Since the file save of archive.info and backup.info are not atomic, then check and update each separately.
@@ -83,19 +81,11 @@ cmdStanzaUpgrade(void)
// Save archive info
if (infoArchiveUpgrade)
{
infoArchiveSaveFile(
infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR,
cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx), cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
}
infoArchiveSaveFile(infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
// Save backup info
if (infoBackupUpgrade)
{
infoBackupSaveFile(
infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx),
cfgOptionIdxStrNull(cfgOptRepoCipherPass, repoIdx));
}
infoBackupSaveFile(infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cfgCipherSpecMainIdx(repoIdx));
if (!(infoArchiveUpgrade || infoBackupUpgrade))
{

View File

@@ -18,7 +18,7 @@ Verify File
FN_EXTERN VerifyResult
verifyFile(
const String *const filePathName, const uint64_t offset, const Variant *const limit, const CompressType compressType,
const Buffer *const fileChecksum, const uint64_t fileSize, const String *const cipherPass)
const Buffer *const fileChecksum, const uint64_t fileSize, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, filePathName); // Fully qualified file name
@@ -27,7 +27,7 @@ verifyFile(
FUNCTION_LOG_PARAM(ENUM, compressType); // Compression type
FUNCTION_LOG_PARAM(BUFFER, fileChecksum); // Checksum for the file
FUNCTION_LOG_PARAM(UINT64, fileSize); // Size of file
FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to access the repo file if encrypted
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); // Cipher spec to access the repo file if encrypted
FUNCTION_LOG_END();
ASSERT(filePathName != NULL);
@@ -45,8 +45,8 @@ verifyFile(
IoFilterGroup *const filterGroup = ioReadFilterGroup(read);
// Add decryption filter
if (cipherPass != NULL)
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTR(cipherPass)));
if (cipherSpecType(cipherSpec) != cipherTypeNone)
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherSpec));
// Add decompression filter
if (compressType != compressTypeNone)

View File

@@ -5,7 +5,7 @@ Verify File
#define COMMAND_VERIFY_FILE_H
#include "common/compress/helper.h"
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
/***********************************************************************************************************************************
File result
@@ -25,6 +25,6 @@ Functions
// Verify a file in the pgBackRest repository
FN_EXTERN VerifyResult verifyFile(
const String *filePathName, uint64_t offset, const Variant *limit, CompressType compressType, const Buffer *fileChecksum,
uint64_t fileSize, const String *cipherPass);
uint64_t fileSize, const CipherSpec *cipherSpec);
#endif

View File

@@ -41,12 +41,12 @@ verifyFileProtocol(PackRead *const param)
const CompressType compressType = (CompressType)pckReadU32P(param);
const Buffer *const fileChecksum = pckReadBinP(param);
const uint64_t fileSize = pckReadU64P(param);
const String *const cipherPass = pckReadStrP(param);
const CipherSpec *const cipherSpec = cipherSpecNewPack(param);
// Return result
pckWriteU32P(
protocolServerResultData(result),
verifyFile(filePathName, offset, limit, compressType, fileChecksum, fileSize, cipherPass));
verifyFile(filePathName, offset, limit, compressType, fileChecksum, fileSize, cipherSpec));
}
MEM_CONTEXT_TEMP_END();

View File

@@ -123,9 +123,8 @@ typedef struct VerifyJobData
String *currentBackup; // In progress backup, if any
const InfoPg *pgHistory; // Database history list
bool backupProcessing; // Are we processing WAL or are we processing backups
const String *manifestCipherPass; // Cipher pass for reading backup manifests
const String *walCipherPass; // Cipher pass for reading WAL files
const String *backupCipherPass; // Cipher pass for reading backup files referenced in a manifest
const CipherSpec *cipherSpecManifest; // Cipher spec for reading backup manifests
const CipherSpec *cipherSpecArchive; // Cipher spec for reading WAL files
unsigned int jobErrorTotal; // Total errors that occurred during the job execution
List *archiveIdResultList; // Archive results
List *backupResultList; // Backup results
@@ -168,11 +167,11 @@ verifyInvalidFileAdd(List *const invalidFileList, const VerifyResult reason, con
Load a file into memory
***********************************************************************************************************************************/
static StorageRead *
verifyFileLoad(const String *const pathFileName, const String *const cipherPass)
verifyFileLoad(const String *const pathFileName, const CipherSpec *const cipherSpec)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, pathFileName); // Fully qualified path/file name
FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to open file if encrypted
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); // Cipher spec to open file if encrypted
FUNCTION_TEST_END();
ASSERT(pathFileName != NULL);
@@ -183,8 +182,7 @@ verifyFileLoad(const String *const pathFileName, const String *const cipherPass)
// *read points to a location within result so update result with contents based on necessary filters
IoRead *const read = storageReadIo(result);
cipherBlockFilterGroupAdd(
ioReadFilterGroup(read), cfgOptionStrId(cfgOptRepoCipherType), cipherModeDecrypt, cipherPass);
cipherBlockFilterGroupAdd(ioReadFilterGroup(read), cipherModeDecrypt, cipherSpec);
ioFilterGroupAdd(ioReadFilterGroup(read), cryptoHashNew(hashTypeSha1));
// If the file is compressed, add a decompression filter
@@ -198,12 +196,12 @@ verifyFileLoad(const String *const pathFileName, const String *const cipherPass)
Get status of info files in the repository
***********************************************************************************************************************************/
static VerifyInfoFile
verifyInfoFile(const String *const pathFileName, const bool keepFile, const String *const cipherPass)
verifyInfoFile(const String *const pathFileName, const bool keepFile, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, pathFileName); // Fully qualified path/file name
FUNCTION_LOG_PARAM(BOOL, keepFile); // Should the file be kept in memory?
FUNCTION_TEST_PARAM(STRING, cipherPass); // Password to open file if encrypted
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec); // Cipher spec to open file if encrypted
FUNCTION_LOG_END();
FUNCTION_AUDIT_STRUCT();
@@ -216,17 +214,17 @@ verifyInfoFile(const String *const pathFileName, const bool keepFile, const Stri
{
TRY_BEGIN()
{
IoRead *const infoRead = storageReadIo(verifyFileLoad(pathFileName, cipherPass));
IoRead *const infoRead = storageReadIo(verifyFileLoad(pathFileName, cipherSpec));
// If directed to keep the loaded file in memory, then move the file into the result, else drain the io and close it
if (keepFile)
{
if (strBeginsWith(pathFileName, INFO_BACKUP_PATH_FILE_STR))
result.backup = infoBackupMove(infoBackupNewLoad(infoRead), memContextPrior());
result.backup = infoBackupMove(infoBackupNewLoad(infoRead, cipherSpec), memContextPrior());
else if (strBeginsWith(pathFileName, INFO_ARCHIVE_PATH_FILE_STR))
result.archive = infoArchiveMove(infoArchiveNewLoad(infoRead), memContextPrior());
result.archive = infoArchiveMove(infoArchiveNewLoad(infoRead, cipherSpec), memContextPrior());
else
result.manifest = manifestMove(manifestNewLoad(infoRead), memContextPrior());
result.manifest = manifestMove(manifestNewLoad(infoRead, cipherSpec), memContextPrior());
}
else
ioReadDrain(infoRead);
@@ -270,8 +268,7 @@ verifyArchiveInfoFile(void)
MEM_CONTEXT_TEMP_BEGIN()
{
// Get the main info file
const VerifyInfoFile verifyArchiveInfo = verifyInfoFile(
INFO_ARCHIVE_PATH_FILE_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass));
const VerifyInfoFile verifyArchiveInfo = verifyInfoFile(INFO_ARCHIVE_PATH_FILE_STR, true, cfgCipherSpecMain());
// If the main file did not error, then report on the copy's status and check checksums
if (verifyArchiveInfo.errorCode == 0)
@@ -281,7 +278,7 @@ verifyArchiveInfoFile(void)
// Attempt to load the copy and report on it's status but don't keep it in memory
const VerifyInfoFile verifyArchiveInfoCopy = verifyInfoFile(
INFO_ARCHIVE_PATH_FILE_COPY_STR, false, cfgOptionStrNull(cfgOptRepoCipherPass));
INFO_ARCHIVE_PATH_FILE_COPY_STR, false, cfgCipherSpecMain());
// If the copy loaded successfully, then check the checksums
if (verifyArchiveInfoCopy.errorCode == 0)
@@ -295,8 +292,7 @@ verifyArchiveInfoFile(void)
else
{
// Attempt to load the copy
const VerifyInfoFile verifyArchiveInfoCopy = verifyInfoFile(
INFO_ARCHIVE_PATH_FILE_COPY_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass));
const VerifyInfoFile verifyArchiveInfoCopy = verifyInfoFile(INFO_ARCHIVE_PATH_FILE_COPY_STR, true, cfgCipherSpecMain());
// If loaded successfully, then return the copy as usable
if (verifyArchiveInfoCopy.errorCode == 0)
@@ -324,8 +320,7 @@ verifyBackupInfoFile(void)
MEM_CONTEXT_TEMP_BEGIN()
{
// Get the main info file
const VerifyInfoFile verifyBackupInfo = verifyInfoFile(
INFO_BACKUP_PATH_FILE_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass));
const VerifyInfoFile verifyBackupInfo = verifyInfoFile(INFO_BACKUP_PATH_FILE_STR, true, cfgCipherSpecMain());
// If the main file did not error, then report on the copy's status and check checksums
if (verifyBackupInfo.errorCode == 0)
@@ -334,8 +329,7 @@ verifyBackupInfoFile(void)
infoBackupMove(result, memContextPrior());
// Attempt to load the copy and report on it's status but don't keep it in memory
const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile(
INFO_BACKUP_PATH_FILE_COPY_STR, false, cfgOptionStrNull(cfgOptRepoCipherPass));
const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile(INFO_BACKUP_PATH_FILE_COPY_STR, false, cfgCipherSpecMain());
// If the copy loaded successfully, then check the checksums
if (verifyBackupInfoCopy.errorCode == 0)
@@ -349,8 +343,7 @@ verifyBackupInfoFile(void)
else
{
// Attempt to load the copy
const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile(
INFO_BACKUP_PATH_FILE_COPY_STR, true, cfgOptionStrNull(cfgOptRepoCipherPass));
const VerifyInfoFile verifyBackupInfoCopy = verifyInfoFile(INFO_BACKUP_PATH_FILE_COPY_STR, true, cfgCipherSpecMain());
// If loaded successfully, then return the copy as usable
if (verifyBackupInfoCopy.errorCode == 0)
@@ -370,12 +363,12 @@ Get the manifest file
***********************************************************************************************************************************/
static Manifest *
verifyManifestFile(
VerifyBackupResult *const backupResult, const String *const cipherPass, bool currentBackup, const InfoPg *const pgHistory,
unsigned int *const jobErrorTotal)
VerifyBackupResult *const backupResult, const CipherSpec *const cipherSpecManifest, bool currentBackup,
const InfoPg *const pgHistory, unsigned int *const jobErrorTotal)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM_P(VERIFY_BACKUP_RESULT, backupResult); // The result set for the backup being processed
FUNCTION_TEST_PARAM(STRING, cipherPass); // Passphrase to access the manifest file
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecManifest); // Cipher spec to access the manifest file
FUNCTION_LOG_PARAM(BOOL, currentBackup); // Is this possibly a backup currently in progress?
FUNCTION_LOG_PARAM(INFO_PG, pgHistory); // Database history
FUNCTION_LOG_PARAM_P(UINT, jobErrorTotal); // Pointer to the overall job error total
@@ -388,7 +381,7 @@ verifyManifestFile(
const String *const fileName = strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupResult->backupLabel));
// Get the main manifest file
const VerifyInfoFile verifyManifestInfo = verifyInfoFile(fileName, true, cipherPass);
const VerifyInfoFile verifyManifestInfo = verifyInfoFile(fileName, true, cipherSpecManifest);
// If the main file did not error, then report on the copy's status and check checksums
if (verifyManifestInfo.errorCode == 0)
@@ -402,7 +395,7 @@ verifyManifestFile(
// Attempt to load the copy and report on it's status but don't keep it in memory
const VerifyInfoFile verifyManifestInfoCopy = verifyInfoFile(
strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), false, cipherPass);
strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), false, cipherSpecManifest);
// If the copy loaded successfully, then check the checksums
if (verifyManifestInfoCopy.errorCode == 0)
@@ -423,7 +416,7 @@ verifyManifestFile(
currentBackup = false;
const VerifyInfoFile verifyManifestInfoCopy = verifyInfoFile(
strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), true, cipherPass);
strNewFmt("%s%s", strZ(fileName), INFO_COPY_EXT), true, cipherSpecManifest);
// If loaded successfully, then return the copy as usable
if (verifyManifestInfoCopy.errorCode == 0)
@@ -662,7 +655,7 @@ verifyBackupSet(VerifyJobData *const jobData, const String *const backupLabel)
{
const Manifest *const manifest = manifestLoadFile(
storageRepo(), strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strZ(backupLabel)),
cfgOptionStrId(cfgOptRepoCipherType), jobData->manifestCipherPass);
jobData->cipherSpecManifest);
// Check files for block incremental
bool hasBlockIncr = false;
@@ -836,7 +829,7 @@ verifyArchive(VerifyJobData *const jobData)
strNewFmt(
STORAGE_REPO_ARCHIVE "/%s/%s/%s", strZ(archiveResult->archiveId), strZ(walPath),
strZ(strLstGet(jobData->walFileList, 0))),
jobData->walCipherPass);
jobData->cipherSpecArchive);
const PgWal walInfo = pgWalFromBuffer(
storageGetP(walRead, .exactSize = PG_WAL_HEADER_SIZE), cfgOptionStrNull(cfgOptPgVersionForce));
@@ -872,7 +865,7 @@ verifyArchive(VerifyJobData *const jobData)
pckWriteU32P(param, compressTypeFromName(filePathName));
pckWriteBinP(param, checksum);
pckWriteU64P(param, archiveResult->pgWalInfo.size);
pckWriteStrP(param, jobData->walCipherPass);
cipherSpecPack(param, jobData->cipherSpecArchive);
// Assign job to result, prepending the archiveId to the key for consistency with backup processing
const String *const jobKey = strNewFmt("%s/%s", strZ(archiveResult->archiveId), strZ(filePathName));
@@ -973,7 +966,7 @@ verifyBackup(VerifyJobData *const jobData)
// Get a usable backup manifest file
Manifest *const manifest = verifyManifestFile(
backupResult, jobData->manifestCipherPass, inProgressBackup, jobData->pgHistory, &jobData->jobErrorTotal);
backupResult, jobData->cipherSpecManifest, inProgressBackup, jobData->pgHistory, &jobData->jobErrorTotal);
// If a usable backup.manifest file is not found
if (manifest == NULL)
@@ -989,15 +982,7 @@ verifyBackup(VerifyJobData *const jobData)
{
// Move the manifest to the jobData for processing
jobData->manifest = manifestMove(manifest, jobData->memContext);
// Initialize the jobData
MEM_CONTEXT_BEGIN(jobData->memContext)
{
// Get the cipher subpass used to decrypt files in the backup and initialize the file list index
jobData->backupCipherPass = strDup(manifestCipherSubPass(jobData->manifest));
jobData->manifestFileIdx = 0;
}
MEM_CONTEXT_END();
jobData->manifestFileIdx = 0;
const ManifestData *const manData = manifestData(jobData->manifest);
@@ -1114,7 +1099,7 @@ verifyBackup(VerifyJobData *const jobData)
pckWriteU32P(param, compressTypeNone);
pckWriteBinP(param, BUF(fileData.checksumRepoSha1, HASH_TYPE_SHA1_SIZE));
pckWriteU64P(param, fileData.sizeRepo);
pckWriteStrP(param, NULL);
cipherSpecPack(param, cipherSpecNewNone());
}
// Else use the file checksum, which may require additional filters, e.g. decompression
else
@@ -1122,7 +1107,7 @@ verifyBackup(VerifyJobData *const jobData)
pckWriteU32P(param, manifestData(jobData->manifest)->backupOptionCompressType);
pckWriteBinP(param, BUF(fileData.checksumSha1, HASH_TYPE_SHA1_SIZE));
pckWriteU64P(param, fileData.size);
pckWriteStrP(param, jobData->backupCipherPass);
cipherSpecPack(param, manifestCipherSpec(jobData->manifest));
}
// Assign job to result (prepend backup label being processed to the key since some files are in a prior
@@ -1639,8 +1624,8 @@ verifyProcess(const bool verboseText)
.walPathList = NULL,
.walFileList = strLstNew(),
.pgHistory = infoArchivePg(archiveInfo),
.manifestCipherPass = infoPgCipherPass(infoBackupPg(backupInfo)),
.walCipherPass = infoPgCipherPass(infoArchivePg(archiveInfo)),
.cipherSpecManifest = infoBackupCipherSpec(backupInfo),
.cipherSpecArchive = infoArchiveCipherSpec(archiveInfo),
.archiveIdResultList = lstNewP(sizeof(VerifyArchiveResult), .comparator = archiveIdComparator),
.backupResultList = lstNewP(sizeof(VerifyBackupResult), .comparator = lstComparatorStr),
};

View File

@@ -384,25 +384,24 @@ cipherBlockInputSame(const THIS_VOID)
/**********************************************************************************************************************************/
FN_EXTERN IoFilter *
cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer *const pass, const CipherBlockNewParam param)
cipherBlockNew(const CipherMode mode, const CipherSpec *const cipherSpec, const CipherBlockNewParam param)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(STRING_ID, mode);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(BUFFER, pass); // Use FUNCTION_TEST so passphrase is not logged
FUNCTION_LOG_PARAM(STRING, param.digest);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_PARAM(BOOL, param.raw);
FUNCTION_LOG_END();
ASSERT(pass != NULL);
ASSERT(!bufEmpty(pass));
ASSERT(cipherSpec != NULL);
ASSERT(cipherSpecType(cipherSpec) != cipherTypeNone);
ASSERT(cipherSpecPass(cipherSpec) != NULL && !bufEmpty(cipherSpecPass(cipherSpec)));
// Init crypto subsystem
cryptoInit();
// Lookup cipher by name. This means the ciphers passed in must exactly match a name expected by OpenSSL. This is a good thing
// since the name required by the openssl command-line tool will match what is used by pgBackRest.
char *const cipherTypeZ = zNewStrId(cipherType);
char *const cipherTypeZ = zNewStrId(cipherSpecType(cipherSpec));
const EVP_CIPHER *cipher = EVP_get_cipherbyname(cipherTypeZ);
if (!cipher)
@@ -410,17 +409,6 @@ cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer
zFree(cipherTypeZ);
// Lookup digest. If not defined it will be set to sha1.
const EVP_MD *digest = NULL;
if (param.digest)
digest = EVP_get_digestbyname(strZ(param.digest));
else
digest = EVP_sha1();
if (!digest)
THROW_FMT(AssertError, "unable to load digest '%s'", strZ(param.digest));
OBJ_NEW_BEGIN(CipherBlock, .childQty = MEM_CONTEXT_QTY_MAX, .callbackQty = 1)
{
*this = (CipherBlock)
@@ -428,8 +416,10 @@ cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer
.mode = mode,
.raw = param.raw,
.cipher = cipher,
.digest = digest,
.pass = bufDup(pass),
// The key is always derived with SHA-1. Deriving it with anything else is not supported yet.
.digest = EVP_sha1(),
.pass = bufDup(cipherSpecPass(cipherSpec)),
};
}
OBJ_NEW_END();
@@ -442,9 +432,7 @@ cipherBlockNew(const CipherMode mode, const CipherType cipherType, const Buffer
PackWrite *const packWrite = pckWriteNewP();
pckWriteU64P(packWrite, mode);
pckWriteU64P(packWrite, cipherType);
pckWriteBinP(packWrite, pass);
pckWriteStrP(packWrite, param.digest);
cipherSpecPack(packWrite, cipherSpec);
pckWriteBoolP(packWrite, param.raw);
pckWriteEndP(packWrite);
@@ -468,12 +456,10 @@ cipherBlockNewPack(const Pack *const paramList)
{
PackRead *const paramListPack = pckReadNew(paramList);
const CipherMode cipherMode = (CipherMode)pckReadU64P(paramListPack);
const CipherType cipherType = (CipherType)pckReadU64P(paramListPack);
const Buffer *const pass = pckReadBinP(paramListPack);
const String *const digest = pckReadStrP(paramListPack);
const CipherSpec *const cipherSpec = cipherSpecNewPack(paramListPack);
const bool raw = pckReadBoolP(paramListPack);
result = ioFilterMove(cipherBlockNewP(cipherMode, cipherType, pass, .digest = digest, .raw = raw), memContextPrior());
result = ioFilterMove(cipherBlockNewP(cipherMode, cipherSpec, .raw = raw), memContextPrior());
}
MEM_CONTEXT_TEMP_END();
@@ -482,20 +468,19 @@ cipherBlockNewPack(const Pack *const paramList)
/**********************************************************************************************************************************/
FN_EXTERN IoFilterGroup *
cipherBlockFilterGroupAdd(IoFilterGroup *const filterGroup, const CipherType type, const CipherMode mode, const String *const pass)
cipherBlockFilterGroupAdd(IoFilterGroup *const filterGroup, const CipherMode mode, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(IO_FILTER_GROUP, filterGroup);
FUNCTION_LOG_PARAM(STRING_ID, type);
FUNCTION_LOG_PARAM(STRING_ID, mode);
FUNCTION_TEST_PARAM(STRING, pass); // Use FUNCTION_TEST so passphrase is not logged
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(filterGroup != NULL);
ASSERT((type == cipherTypeNone && pass == NULL) || (type != cipherTypeNone && pass != NULL));
ASSERT(cipherSpec != NULL);
if (type != cipherTypeNone)
ioFilterGroupAdd(filterGroup, cipherBlockNewP(mode, type, BUFSTR(pass)));
if (cipherSpecType(cipherSpec) != cipherTypeNone)
ioFilterGroupAdd(filterGroup, cipherBlockNewP(mode, cipherSpec));
FUNCTION_LOG_RETURN(IO_FILTER_GROUP, filterGroup);
}

View File

@@ -4,7 +4,7 @@ Block Cipher Header
#ifndef COMMON_CRYPTO_CIPHERBLOCK_H
#define COMMON_CRYPTO_CIPHERBLOCK_H
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
#include "common/io/filter/group.h"
/***********************************************************************************************************************************
@@ -18,21 +18,19 @@ Constructors
typedef struct CipherBlockNewParam
{
VAR_PARAM_HEADER;
const String *digest; // Digest to use (defaults to SHA-1)
bool raw; // Omit header magic to save space
} CipherBlockNewParam;
#define cipherBlockNewP(mode, cipherType, pass, ...) \
cipherBlockNew(mode, cipherType, pass, (CipherBlockNewParam){VAR_PARAM_INIT, __VA_ARGS__})
#define cipherBlockNewP(mode, cipherSpec, ...) \
cipherBlockNew(mode, cipherSpec, (CipherBlockNewParam){VAR_PARAM_INIT, __VA_ARGS__})
FN_EXTERN IoFilter *cipherBlockNew(CipherMode mode, CipherType cipherType, const Buffer *pass, CipherBlockNewParam param);
FN_EXTERN IoFilter *cipherBlockNew(CipherMode mode, const CipherSpec *cipherSpec, CipherBlockNewParam param);
FN_EXTERN IoFilter *cipherBlockNewPack(const Pack *paramList);
/***********************************************************************************************************************************
Helper functions
***********************************************************************************************************************************/
// Add a block cipher to an io object
FN_EXTERN IoFilterGroup *cipherBlockFilterGroupAdd(
IoFilterGroup *filterGroup, CipherType type, CipherMode mode, const String *pass);
// Add a block cipher to an io object. Nothing is added when the repository is not encrypted.
FN_EXTERN IoFilterGroup *cipherBlockFilterGroupAdd(IoFilterGroup *filterGroup, CipherMode mode, const CipherSpec *cipherSpec);
#endif

96
src/common/crypto/spec.c Normal file
View File

@@ -0,0 +1,96 @@
/***********************************************************************************************************************************
Cipher Spec
***********************************************************************************************************************************/
#include <build.h>
#include "common/crypto/spec.h"
#include "common/debug.h"
#include "common/log.h"
/***********************************************************************************************************************************
Object type
***********************************************************************************************************************************/
struct CipherSpec
{
CipherSpecPub pub; // Publicly accessible variables
};
/**********************************************************************************************************************************/
FN_EXTERN CipherSpec *
cipherSpecNew(const CipherType type, const Buffer *const pass)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING_ID, type);
FUNCTION_TEST_PARAM(BUFFER, pass);
FUNCTION_TEST_END();
ASSERT((type == cipherTypeNone) == (pass == NULL));
ASSERT(pass == NULL || !bufEmpty(pass));
OBJ_NEW_BEGIN(CipherSpec, .childQty = MEM_CONTEXT_QTY_MAX)
{
*this = (CipherSpec){.pub = {.type = type}};
if (this->pub.type != cipherTypeNone)
this->pub.pass = bufDup(pass);
}
OBJ_NEW_END();
FUNCTION_TEST_RETURN(CIPHER_SPEC, this);
}
/**********************************************************************************************************************************/
FN_EXTERN CipherSpec *
cipherSpecNewPack(PackRead *const packRead)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(PACK_READ, packRead);
FUNCTION_TEST_END();
ASSERT(packRead != NULL);
OBJ_NEW_BEGIN(CipherSpec, .childQty = MEM_CONTEXT_QTY_MAX)
{
*this = (CipherSpec){.pub = {.type = (CipherType)pckReadStrIdP(packRead)}};
// Nothing else was written when there is no cipher. The pass is read here rather than copied in since this context is the
// one it belongs in.
if (this->pub.type != cipherTypeNone)
this->pub.pass = pckReadBinP(packRead);
}
OBJ_NEW_END();
FUNCTION_TEST_RETURN(CIPHER_SPEC, this);
}
/**********************************************************************************************************************************/
FN_EXTERN void
cipherSpecPack(PackWrite *const packWrite, const CipherSpec *const this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(PACK_WRITE, packWrite);
FUNCTION_TEST_PARAM(CIPHER_SPEC, this);
FUNCTION_TEST_END();
ASSERT(packWrite != NULL);
ASSERT(this != NULL);
pckWriteStrIdP(packWrite, cipherSpecType(this));
// Nothing else is needed when there is no cipher
if (cipherSpecType(this) != cipherTypeNone)
pckWriteBinP(packWrite, cipherSpecPass(this));
FUNCTION_TEST_RETURN_VOID();
}
/**********************************************************************************************************************************/
FN_EXTERN void
cipherSpecToLog(const CipherSpec *const this, StringStatic *const debugLog)
{
char typeZ[STRID_MAX + 1];
strIdToZ(cipherSpecType(this), typeZ);
// The pass is never logged
strStcFmt(debugLog, "{type: %s}", typeZ);
}

101
src/common/crypto/spec.h Normal file
View File

@@ -0,0 +1,101 @@
/***********************************************************************************************************************************
Cipher Spec
Everything needed to encrypt or decrypt, kept together so that adding to it does not mean changing every function and protocol
message that carries it.
The passphrase (pass) contains the bytes the key is derived from. There is no pass when the type is none, and the pass is never
logged.
***********************************************************************************************************************************/
#ifndef COMMON_CRYPTO_SPEC_H
#define COMMON_CRYPTO_SPEC_H
/***********************************************************************************************************************************
Object type
***********************************************************************************************************************************/
typedef struct CipherSpec CipherSpec;
#include "common/crypto/common.h"
#include "common/type/buffer.h"
#include "common/type/object.h"
#include "common/type/pack.h"
/***********************************************************************************************************************************
Constructors
***********************************************************************************************************************************/
// Create from a pass
FN_EXTERN CipherSpec *cipherSpecNew(CipherType type, const Buffer *pass);
// Create for no encryption
FN_INLINE_ALWAYS CipherSpec *
cipherSpecNewNone(void)
{
return cipherSpecNew(cipherTypeNone, NULL);
}
// Create from a pack written by cipherSpecPack()
FN_EXTERN CipherSpec *cipherSpecNewPack(PackRead *packRead);
/***********************************************************************************************************************************
Getters/Setters
***********************************************************************************************************************************/
typedef struct CipherSpecPub
{
CipherType type; // Cipher type, none when not encrypted
const Buffer *pass; // Passphrase text or key bytes
} CipherSpecPub;
// Cipher type
FN_INLINE_ALWAYS CipherType
cipherSpecType(const CipherSpec *const this)
{
return THIS_PUB(CipherSpec)->type;
}
// Passphrase text or key bytes
FN_INLINE_ALWAYS const Buffer *
cipherSpecPass(const CipherSpec *const this)
{
return THIS_PUB(CipherSpec)->pass;
}
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
// Duplicate
FN_INLINE_ALWAYS CipherSpec *
cipherSpecDup(const CipherSpec *const this)
{
return cipherSpecNew(cipherSpecType(this), cipherSpecPass(this));
}
// Write to a pack so it can be passed over a protocol
FN_EXTERN void cipherSpecPack(PackWrite *packWrite, const CipherSpec *this);
// Move to a new parent mem context
FN_INLINE_ALWAYS CipherSpec *
cipherSpecMove(CipherSpec *const this, MemContext *const parentNew)
{
return objMove(this, parentNew);
}
/***********************************************************************************************************************************
Destructor
***********************************************************************************************************************************/
FN_INLINE_ALWAYS void
cipherSpecFree(CipherSpec *const this)
{
objFree(this);
}
/***********************************************************************************************************************************
Macros for function logging
***********************************************************************************************************************************/
FN_EXTERN void cipherSpecToLog(const CipherSpec *this, StringStatic *debugLog);
#define FUNCTION_LOG_CIPHER_SPEC_TYPE \
CipherSpec *
#define FUNCTION_LOG_CIPHER_SPEC_FORMAT(value, buffer, bufferSize) \
FUNCTION_LOG_OBJECT_FORMAT(value, cipherSpecToLog, buffer, bufferSize)
#endif

View File

@@ -1078,3 +1078,39 @@ cfgOptionInvalidate(const ConfigOption optionId)
FUNCTION_TEST_RETURN_VOID();
}
/**********************************************************************************************************************************/
FN_EXTERN const CipherSpec *
cfgCipherSpecMainIdx(const unsigned int repoIdx)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(UINT, repoIdx);
FUNCTION_TEST_END();
ASSERT(repoIdx < cfgOptionGroupIdxTotal(cfgOptGrpRepo));
// Allocate a slot per repo. Each repo has its own cipher type and passphrase so cipher spec cannot be shared between them.
if (configLocal->cipherSpecMain == NULL)
{
MEM_CONTEXT_BEGIN(configLocal->memContext)
{
configLocal->cipherSpecMain = memNewPtrArray(cfgOptionGroupIdxTotal(cfgOptGrpRepo));
}
MEM_CONTEXT_END();
}
// Get cipher spec if it doesn't exist
if (configLocal->cipherSpecMain[repoIdx] == NULL)
{
MEM_CONTEXT_BEGIN(configLocal->memContext)
{
const CipherType cipherType = cfgOptionIdxStrId(cfgOptRepoCipherType, repoIdx);
configLocal->cipherSpecMain[repoIdx] = cipherSpecNew(
cipherType, cipherType == cipherTypeNone ? NULL : BUFSTR(cfgOptionIdxStr(cfgOptRepoCipherPass, repoIdx)));
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RETURN_CONST(CIPHER_SPEC, configLocal->cipherSpecMain[repoIdx]);
}

View File

@@ -7,6 +7,7 @@ sets the command and options and determines which options are valid for a comman
#ifndef CONFIG_CONFIG_H
#define CONFIG_CONFIG_H
#include "common/crypto/spec.h"
#include "common/log.h"
#include "common/type/stringId.h"
#include "common/type/stringList.h"
@@ -238,6 +239,21 @@ FN_EXTERN bool cfgOptionValid(ConfigOption optionId);
FN_EXTERN bool cfgOptionTest(ConfigOption optionId);
FN_EXTERN bool cfgOptionIdxTest(ConfigOption optionId, unsigned int optionIdx);
/***********************************************************************************************************************************
Cipher Functions
Main cipher spec for a repository, built from the cipher options and cached per repo since the options cannot change while a command
runs. This is the top of the chain. The info files are read with it and each of those carries the cipher spec for the files that
depend on it, so nothing further down needs to consult the options again.
***********************************************************************************************************************************/
FN_EXTERN const CipherSpec *cfgCipherSpecMainIdx(unsigned int repoIdx);
FN_INLINE_ALWAYS const CipherSpec *
cfgCipherSpecMain(void)
{
return cfgCipherSpecMainIdx(cfgOptionIdxDefault(cfgOptRepoCipherType));
}
/***********************************************************************************************************************************
Option Source Enum

View File

@@ -82,6 +82,8 @@ typedef struct Config
ConfigOptionGroupData optionGroup[CFG_OPTION_GROUP_TOTAL]; // Option group data
ConfigOptionData option[CFG_OPTION_TOTAL]; // Option data
CipherSpec **cipherSpecMain; // Main cipher spec for the cipher options by repo index
} Config;
/***********************************************************************************************************************************

View File

@@ -94,10 +94,10 @@ BUFFER_STRDEF_STATIC(INFO_CHECKSUM_END_BUF, "}}");
/**********************************************************************************************************************************/
FN_EXTERN Info *
infoNew(const String *const cipherPass)
infoNew(const CipherSpec *const cipherSpecSub)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_TEST_PARAM(STRING, cipherPass); // Use FUNCTION_TEST so cipher is not logged
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub);
FUNCTION_LOG_END();
OBJ_NEW_BEGIN(Info, .childQty = MEM_CONTEXT_QTY_MAX)
@@ -105,7 +105,7 @@ infoNew(const String *const cipherPass)
*this = (Info){};
// Cipher used to encrypt/decrypt subsequent dependent files. Value may be NULL.
infoCipherPassSet(this, cipherPass);
infoCipherSpecSet(this, cipherSpecSub);
this->pub.backrestVersion = STRDEF(PROJECT_VERSION);
}
OBJ_NEW_END();
@@ -120,10 +120,12 @@ infoNew(const String *const cipherPass)
#define INFO_KEY_CIPHER_PASS "cipher-pass"
FN_EXTERN Info *
infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, void *const callbackData)
infoNewLoad(
IoRead *const read, const CipherSpec *const cipherSpec, InfoLoadNewCallback *const callbackFunction, void *const callbackData)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(IO_READ, read);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
FUNCTION_LOG_PARAM_P(VOID, callbackData);
FUNCTION_LOG_END();
@@ -131,6 +133,7 @@ infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, voi
FUNCTION_AUDIT_CALLBACK();
ASSERT(read != NULL);
ASSERT(cipherSpec != NULL);
ASSERT(callbackFunction != NULL);
ASSERT(callbackData != NULL);
@@ -213,7 +216,9 @@ infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, voi
{
MEM_CONTEXT_OBJ_BEGIN(this)
{
this->pub.cipherPass = varStr(jsonToVar(value->value));
// The dependent files are encrypted with the same cipher type as this one
this->pub.cipherSpec = cipherSpecNew(
cipherSpecType(cipherSpec), BUFSTR(varStr(jsonToVar(value->value))));
}
MEM_CONTEXT_OBJ_END();
}
@@ -250,6 +255,10 @@ infoNewLoad(IoRead *const read, InfoLoadNewCallback *const callbackFunction, voi
}
}
MEM_CONTEXT_TEMP_END();
// A file with no cipher section has no encrypted dependent files
if (this->pub.cipherSpec == NULL)
infoCipherSpecSet(this, NULL);
}
OBJ_NEW_END();
@@ -366,10 +375,12 @@ infoSave(Info *const this, IoWrite *const write, InfoSaveCallback *const callbac
infoSaveValue(&data, INFO_SECTION_BACKREST, INFO_KEY_VERSION, jsonFromVar(VARSTRDEF(PROJECT_VERSION)));
// Add cipher passphrase if defined
if (infoCipherPass(this) != NULL)
if (cipherSpecType(infoCipherSpec(this)) != cipherTypeNone)
{
callbackFunction(callbackData, STRDEF(INFO_SECTION_CIPHER), &data);
infoSaveValue(&data, INFO_SECTION_CIPHER, INFO_KEY_CIPHER_PASS, jsonFromVar(VARSTR(infoCipherPass(this))));
infoSaveValue(
&data, INFO_SECTION_CIPHER, INFO_KEY_CIPHER_PASS,
jsonFromVar(VARSTR(strNewBuf(cipherSpecPass(infoCipherSpec(this))))));
}
// Flush out any additional sections
@@ -395,11 +406,11 @@ infoSave(Info *const this, IoWrite *const write, InfoSaveCallback *const callbac
Getters/Setters
***********************************************************************************************************************************/
FN_EXTERN void
infoCipherPassSet(Info *const this, const String *const cipherPass)
infoCipherSpecSet(Info *const this, const CipherSpec *const cipherSpec)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(INFO, this);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_TEST_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_TEST_END();
FUNCTION_AUDIT_IF(memContextCurrent() != objMemContext(this)); // Do not audit calls from within the object
@@ -408,7 +419,8 @@ infoCipherPassSet(Info *const this, const String *const cipherPass)
MEM_CONTEXT_OBJ_BEGIN(this)
{
this->pub.cipherPass = strDup(cipherPass);
// Copy so the caller is free to release what was passed in, and so the getter never returns NULL
this->pub.cipherSpec = cipherSpec == NULL ? cipherSpecNewNone() : cipherSpecDup(cipherSpec);
}
MEM_CONTEXT_OBJ_END();

View File

@@ -10,6 +10,7 @@ Object type
typedef struct Info Info;
typedef struct InfoSave InfoSave;
#include "common/crypto/spec.h"
#include "common/ini.h"
#include "common/type/json.h"
#include "storage/storage.h"
@@ -38,10 +39,12 @@ typedef void InfoSaveCallback(void *data, const String *sectionNext, InfoSave *i
/***********************************************************************************************************************************
Constructors
***********************************************************************************************************************************/
FN_EXTERN Info *infoNew(const String *cipherPassSub);
FN_EXTERN Info *infoNew(const CipherSpec *cipherSpecSub);
// Create new object and load contents from a file
FN_EXTERN Info *infoNewLoad(IoRead *read, InfoLoadNewCallback *callbackFunction, void *callbackData);
// Create new object and load contents from a file. The cipher spec the file is read with supplies the type for the cipher spec
// built from the pass stored in it.
FN_EXTERN Info *infoNewLoad(
IoRead *read, const CipherSpec *cipherSpec, InfoLoadNewCallback *callbackFunction, void *callbackData);
/***********************************************************************************************************************************
Getters/Setters
@@ -49,17 +52,19 @@ Getters/Setters
typedef struct InfoPub
{
const String *backrestVersion; // pgBackRest version
const String *cipherPass; // Cipher passphrase if set
const CipherSpec *cipherSpec; // Cipher spec for dependent files
} InfoPub;
// Cipher passphrase if set
FN_INLINE_ALWAYS const String *
infoCipherPass(const Info *const this)
// Cipher spec for the files that depend on this one, e.g. the manifest for backup.info. Never NULL, so it can be handed on
// without a check, and none when there is no pass.
FN_INLINE_ALWAYS const CipherSpec *
infoCipherSpec(const Info *const this)
{
return THIS_PUB(Info)->cipherPass;
return THIS_PUB(Info)->cipherSpec;
}
FN_EXTERN void infoCipherPassSet(Info *this, const String *cipherPass);
// Set cipher spec for dependent files. NULL means they are not encrypted.
FN_EXTERN void infoCipherSpecSet(Info *this, const CipherSpec *cipherSpec);
// pgBackRest version
FN_INLINE_ALWAYS const String *

View File

@@ -57,12 +57,12 @@ infoArchiveNewInternal(void)
/**********************************************************************************************************************************/
FN_EXTERN InfoArchive *
infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const String *const cipherPassSub)
infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *const cipherSpecSub)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(UINT, pgVersion);
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub);
FUNCTION_LOG_END();
ASSERT(pgVersion > 0 && pgSystemId > 0);
@@ -74,7 +74,7 @@ infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const St
this = infoArchiveNewInternal();
// Initialize the pg data
this->pub.infoPg = infoPgNew(infoPgArchive, cipherPassSub);
this->pub.infoPg = infoPgNew(infoPgArchive, cipherSpecSub);
infoArchivePgSet(this, pgVersion, pgSystemId);
}
OBJ_NEW_END();
@@ -84,10 +84,11 @@ infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const St
/**********************************************************************************************************************************/
FN_EXTERN InfoArchive *
infoArchiveNewLoad(IoRead *const read)
infoArchiveNewLoad(IoRead *const read, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(IO_READ, read);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(read != NULL);
@@ -97,7 +98,7 @@ infoArchiveNewLoad(IoRead *const read)
OBJ_NEW_BASE_BEGIN(InfoArchive, .childQty = MEM_CONTEXT_QTY_MAX)
{
this = infoArchiveNewInternal();
this->pub.infoPg = infoPgNewLoad(read, infoPgArchive, NULL, NULL);
this->pub.infoPg = infoPgNewLoad(read, infoPgArchive, cipherSpec, NULL, NULL);
}
OBJ_NEW_END();
@@ -207,8 +208,7 @@ typedef struct InfoArchiveLoadFileData
MemContext *memContext; // Mem context
const Storage *storage; // Storage to load from
const String *fileName; // Base filename
CipherType cipherType; // Cipher type
const String *cipherPass; // Cipher passphrase
const CipherSpec *cipherSpec; // Cipher spec
InfoArchive *infoArchive; // Loaded infoArchive object
} InfoArchiveLoadFileData;
@@ -234,11 +234,12 @@ infoArchiveLoadFileCallback(void *const data, const unsigned int try)
// Attempt to load the file
IoRead *const read = storageReadIo(storageNewReadP(loadData->storage, fileName));
cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass);
cipherBlockFilterGroupAdd(
ioReadFilterGroup(read), cipherModeDecrypt, loadData->cipherSpec);
MEM_CONTEXT_BEGIN(loadData->memContext)
{
loadData->infoArchive = infoArchiveNewLoad(read);
loadData->infoArchive = infoArchiveNewLoad(read, loadData->cipherSpec);
result = true;
}
MEM_CONTEXT_END();
@@ -251,26 +252,24 @@ infoArchiveLoadFileCallback(void *const data, const unsigned int try)
FN_EXTERN InfoArchive *
infoArchiveLoadFile(
const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass)
const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
ASSERT(cipherSpec != NULL);
InfoArchiveLoadFileData data =
{
.memContext = memContextCurrent(),
.storage = storage,
.fileName = fileName,
.cipherType = cipherType,
.cipherPass = cipherPass,
.cipherSpec = cipherSpec,
};
MEM_CONTEXT_TEMP_BEGIN()
@@ -304,28 +303,26 @@ infoArchiveLoadFile(
/**********************************************************************************************************************************/
FN_EXTERN void
infoArchiveSaveFile(
InfoArchive *const infoArchive, const Storage *const storage, const String *const fileName, const CipherType cipherType,
const String *const cipherPass)
InfoArchive *const infoArchive, const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(INFO_ARCHIVE, infoArchive);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(infoArchive != NULL);
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
ASSERT(cipherSpec != NULL);
MEM_CONTEXT_TEMP_BEGIN()
{
// Write output into a buffer since it needs to be saved to storage twice
Buffer *const buffer = bufNew(ioBufferSize());
IoWrite *const write = ioBufferWriteNew(buffer);
cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherType, cipherModeEncrypt, cipherPass);
cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherModeEncrypt, cipherSpec);
infoArchiveSave(infoArchive, write);
// Save the file and make a copy

View File

@@ -9,7 +9,7 @@ Object type
***********************************************************************************************************************************/
typedef struct InfoArchive InfoArchive;
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
#include "common/type/object.h"
#include "common/type/string.h"
#include "info/infoPg.h"
@@ -29,10 +29,10 @@ STRING_DECLARE(INFO_ARCHIVE_PATH_FILE_COPY_STR);
/***********************************************************************************************************************************
Constructors
***********************************************************************************************************************************/
FN_EXTERN InfoArchive *infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const String *cipherPassSub);
FN_EXTERN InfoArchive *infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const CipherSpec *cipherSpecSub);
// Create new object and load contents from IoRead
FN_EXTERN InfoArchive *infoArchiveNewLoad(IoRead *read);
FN_EXTERN InfoArchive *infoArchiveNewLoad(IoRead *read, const CipherSpec *cipherSpec);
/***********************************************************************************************************************************
Getters/Setters
@@ -59,11 +59,11 @@ infoArchiveId(const InfoArchive *const this)
return infoPgArchiveId(infoArchivePg(this), infoPgDataCurrentId(infoArchivePg(this)));
}
// Cipher passphrase
FN_INLINE_ALWAYS const String *
infoArchiveCipherPass(const InfoArchive *const this)
// Cipher spec for dependent files
FN_INLINE_ALWAYS const CipherSpec *
infoArchiveCipherSpec(const InfoArchive *const this)
{
return infoPgCipherPass(infoArchivePg(this));
return infoPgCipherSpec(infoArchivePg(this));
}
/***********************************************************************************************************************************
@@ -93,12 +93,11 @@ infoArchiveFree(InfoArchive *const this)
Helper functions
***********************************************************************************************************************************/
// Load archive info
FN_EXTERN InfoArchive *infoArchiveLoadFile(
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
FN_EXTERN InfoArchive *infoArchiveLoadFile(const Storage *storage, const String *fileName, const CipherSpec *cipherSpec);
// Save archive info
FN_EXTERN void infoArchiveSaveFile(
InfoArchive *infoArchive, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
InfoArchive *infoArchive, const Storage *storage, const String *fileName, const CipherSpec *cipherSpec);
/***********************************************************************************************************************************
Macros for function logging

View File

@@ -66,13 +66,14 @@ infoBackupNewInternal(void)
/**********************************************************************************************************************************/
FN_EXTERN InfoBackup *
infoBackupNew(
const unsigned int pgVersion, const uint64_t pgSystemId, const unsigned int pgCatalogVersion, const String *const cipherPassSub)
const unsigned int pgVersion, const uint64_t pgSystemId, const unsigned int pgCatalogVersion,
const CipherSpec *const cipherSpecSub)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(UINT, pgVersion);
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
FUNCTION_LOG_PARAM(UINT, pgCatalogVersion);
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub);
FUNCTION_LOG_END();
ASSERT(pgVersion > 0 && pgSystemId > 0 && pgCatalogVersion > 0);
@@ -84,7 +85,7 @@ infoBackupNew(
this = infoBackupNewInternal();
// Initialize the pg data
this->pub.infoPg = infoPgNew(infoPgBackup, cipherPassSub);
this->pub.infoPg = infoPgNew(infoPgBackup, cipherSpecSub);
infoBackupPgSet(this, pgVersion, pgSystemId, pgCatalogVersion);
}
OBJ_NEW_END();
@@ -233,10 +234,11 @@ infoBackupLoadCallback(void *const data, const String *const section, const Stri
/**********************************************************************************************************************************/
FN_EXTERN InfoBackup *
infoBackupNewLoad(IoRead *const read)
infoBackupNewLoad(IoRead *const read, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(IO_READ, read);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(read != NULL);
@@ -246,7 +248,7 @@ infoBackupNewLoad(IoRead *const read)
OBJ_NEW_BASE_BEGIN(InfoBackup, .childQty = MEM_CONTEXT_QTY_MAX)
{
this = infoBackupNewInternal();
this->pub.infoPg = infoPgNewLoad(read, infoPgBackup, infoBackupLoadCallback, this);
this->pub.infoPg = infoPgNewLoad(read, infoPgBackup, cipherSpec, infoBackupLoadCallback, this);
this->pub.updated = false;
}
OBJ_NEW_END();
@@ -670,8 +672,7 @@ typedef struct InfoBackupLoadFileData
MemContext *memContext; // Mem context
const Storage *storage; // Storage to load from
const String *fileName; // Base filename
CipherType cipherType; // Cipher type
const String *cipherPass; // Cipher passphrase
const CipherSpec *cipherSpec; // Cipher spec
InfoBackup *infoBackup; // Loaded infoBackup object
} InfoBackupLoadFileData;
@@ -697,11 +698,12 @@ infoBackupLoadFileCallback(void *const data, const unsigned int try)
// Attempt to load the file
IoRead *const read = storageReadIo(storageNewReadP(loadData->storage, fileName));
cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass);
cipherBlockFilterGroupAdd(
ioReadFilterGroup(read), cipherModeDecrypt, loadData->cipherSpec);
MEM_CONTEXT_BEGIN(loadData->memContext)
{
loadData->infoBackup = infoBackupNewLoad(read);
loadData->infoBackup = infoBackupNewLoad(read, loadData->cipherSpec);
result = true;
}
MEM_CONTEXT_END();
@@ -714,26 +716,24 @@ infoBackupLoadFileCallback(void *const data, const unsigned int try)
FN_EXTERN InfoBackup *
infoBackupLoadFile(
const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass)
const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
ASSERT(cipherSpec != NULL);
InfoBackupLoadFileData data =
{
.memContext = memContextCurrent(),
.storage = storage,
.fileName = fileName,
.cipherType = cipherType,
.cipherPass = cipherPass,
.cipherSpec = cipherSpec,
};
MEM_CONTEXT_TEMP_BEGIN()
@@ -786,20 +786,19 @@ infoBackupSetExists(const InfoBackup *const this, const String *const backupSet)
FN_EXTERN InfoBackup *
infoBackupLoadFileReconstruct(
const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass)
const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
ASSERT(cipherSpec != NULL);
InfoBackup *const infoBackup = infoBackupLoadFile(storage, fileName, cipherType, cipherPass);
InfoBackup *const infoBackup = infoBackupLoadFile(storage, fileName, cipherSpec);
MEM_CONTEXT_TEMP_BEGIN()
{
@@ -865,8 +864,7 @@ infoBackupLoadFileReconstruct(
if (storageExistsP(storage, manifestFileName))
{
bool found = false;
const Manifest *const manifest = manifestLoadFile(
storage, manifestFileName, cipherType, infoPgCipherPass(infoBackupPg(infoBackup)));
const Manifest *const manifest = manifestLoadFile(storage, manifestFileName, infoBackupCipherSpec(infoBackup));
const ManifestData *const manData = manifestData(manifest);
// If the pg data for the manifest exists in the history, then add it to current, but if something doesn't match
@@ -902,21 +900,19 @@ infoBackupLoadFileReconstruct(
/**********************************************************************************************************************************/
FN_EXTERN void
infoBackupSaveFile(
InfoBackup *const infoBackup, const Storage *const storage, const String *const fileName, const CipherType cipherType,
const String *const cipherPass)
InfoBackup *const infoBackup, const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(INFO_BACKUP, infoBackup);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(infoBackup != NULL);
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
ASSERT(cipherSpec != NULL);
if (infoBackup->pub.updated)
{
@@ -925,7 +921,7 @@ infoBackupSaveFile(
// Write output into a buffer since it needs to be saved to storage twice
Buffer *const buffer = bufNew(ioBufferSize());
IoWrite *const write = ioBufferWriteNew(buffer);
cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherType, cipherModeEncrypt, cipherPass);
cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherModeEncrypt, cipherSpec);
infoBackupSave(infoBackup, write);
// Save the file and make a copy

View File

@@ -21,6 +21,7 @@ typedef enum
backupTypeIncr = STRID5("incr", 0x90dc90),
} BackupType;
#include "common/crypto/spec.h"
#include "common/type/object.h"
#include "common/type/string.h"
#include "common/type/stringList.h"
@@ -77,10 +78,10 @@ typedef struct InfoBackupData
Constructors
***********************************************************************************************************************************/
FN_EXTERN InfoBackup *infoBackupNew(
unsigned int pgVersion, uint64_t pgSystemId, unsigned int pgCatalogVersion, const String *cipherPassSub);
unsigned int pgVersion, uint64_t pgSystemId, unsigned int pgCatalogVersion, const CipherSpec *cipherSpecSub);
// Create new object and load contents from IoRead
FN_EXTERN InfoBackup *infoBackupNewLoad(IoRead *read);
FN_EXTERN InfoBackup *infoBackupNewLoad(IoRead *read, const CipherSpec *cipherSpec);
/***********************************************************************************************************************************
Getters/Setters
@@ -102,11 +103,11 @@ infoBackupPg(const InfoBackup *const this)
FN_EXTERN InfoBackup *infoBackupPgSet(InfoBackup *this, unsigned int pgVersion, uint64_t pgSystemId, unsigned int pgCatalogVersion);
// Cipher passphrase
FN_INLINE_ALWAYS const String *
infoBackupCipherPass(const InfoBackup *const this)
// Cipher spec for dependent files
FN_INLINE_ALWAYS const CipherSpec *
infoBackupCipherSpec(const InfoBackup *const this)
{
return infoPgCipherPass(infoBackupPg(this));
return infoPgCipherSpec(infoBackupPg(this));
}
// Return a structure of the backup data from a specific index
@@ -173,16 +174,15 @@ infoBackupFree(InfoBackup *const this)
Helper functions
***********************************************************************************************************************************/
// Load backup info
FN_EXTERN InfoBackup *infoBackupLoadFile(
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
FN_EXTERN InfoBackup *infoBackupLoadFile(const Storage *storage, const String *fileName, const CipherSpec *cipherSpec);
// Load backup info and update it by adding valid backups from the repo or removing backups no longer in the repo
FN_EXTERN InfoBackup *infoBackupLoadFileReconstruct(
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
const Storage *storage, const String *fileName, const CipherSpec *cipherSpec);
// Save backup info
FN_EXTERN void infoBackupSaveFile(
InfoBackup *infoBackup, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
InfoBackup *infoBackup, const Storage *storage, const String *fileName, const CipherSpec *cipherSpec);
/***********************************************************************************************************************************
Macros for function logging

View File

@@ -62,11 +62,11 @@ infoPgNewInternal(const InfoPgType type)
/**********************************************************************************************************************************/
FN_EXTERN InfoPg *
infoPgNew(const InfoPgType type, const String *const cipherPassSub)
infoPgNew(const InfoPgType type, const CipherSpec *const cipherSpecSub)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING_ID, type);
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpecSub);
FUNCTION_LOG_END();
InfoPg *this;
@@ -74,7 +74,7 @@ infoPgNew(const InfoPgType type, const String *const cipherPassSub)
OBJ_NEW_BASE_BEGIN(InfoPg, .childQty = MEM_CONTEXT_QTY_MAX)
{
this = infoPgNewInternal(type);
this->pub.info = infoNew(cipherPassSub);
this->pub.info = infoNew(cipherSpecSub);
}
OBJ_NEW_END();
@@ -155,11 +155,14 @@ infoPgLoadCallback(void *const data, const String *const section, const String *
}
FN_EXTERN InfoPg *
infoPgNewLoad(IoRead *const read, const InfoPgType type, InfoLoadNewCallback *const callbackFunction, void *const callbackData)
infoPgNewLoad(
IoRead *const read, const InfoPgType type, const CipherSpec *const cipherSpec, InfoLoadNewCallback *const callbackFunction,
void *const callbackData)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(IO_READ, read);
FUNCTION_LOG_PARAM(STRING_ID, type);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
FUNCTION_LOG_PARAM_P(VOID, callbackData);
FUNCTION_LOG_END();
@@ -185,7 +188,7 @@ infoPgNewLoad(IoRead *const read, const InfoPgType type, InfoLoadNewCallback *co
.infoPg = this,
};
this->pub.info = infoNewLoad(read, infoPgLoadCallback, &loadData);
this->pub.info = infoNewLoad(read, cipherSpec, infoPgLoadCallback, &loadData);
CHECK(FormatError, !lstEmpty(this->pub.history), "history is missing");
CHECK(FormatError, loadData.currentId > 0, "current id is missing");

View File

@@ -47,10 +47,11 @@ typedef enum
/***********************************************************************************************************************************
Constructors
***********************************************************************************************************************************/
FN_EXTERN InfoPg *infoPgNew(InfoPgType type, const String *cipherPassSub);
FN_EXTERN InfoPg *infoPgNew(InfoPgType type, const CipherSpec *cipherSpecSub);
// Create new object and load contents from a file
FN_EXTERN InfoPg *infoPgNewLoad(IoRead *read, InfoPgType type, InfoLoadNewCallback *callbackFunction, void *callbackData);
FN_EXTERN InfoPg *infoPgNewLoad(
IoRead *read, InfoPgType type, const CipherSpec *cipherSpec, InfoLoadNewCallback *callbackFunction, void *callbackData);
/***********************************************************************************************************************************
Getters/Setters
@@ -71,11 +72,11 @@ infoPgInfo(const InfoPg *const this)
return THIS_PUB(InfoPg)->info;
}
// Return the cipher passphrase
FN_INLINE_ALWAYS const String *
infoPgCipherPass(const InfoPg *const this)
// Cipher spec for dependent files
FN_INLINE_ALWAYS const CipherSpec *
infoPgCipherSpec(const InfoPg *const this)
{
return infoCipherPass(infoPgInfo(this));
return infoCipherSpec(infoPgInfo(this));
}
// Return current pgId from the history

View File

@@ -669,10 +669,11 @@ manifestBuildComplete(
/**********************************************************************************************************************************/
FN_EXTERN Manifest *
manifestNewLoad(IoRead *const read)
manifestNewLoad(IoRead *const read, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(IO_READ, read);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(read != NULL);
@@ -703,7 +704,7 @@ manifestNewLoad(IoRead *const read)
}
MEM_CONTEXT_END();
this->pub.info = infoNewLoad(read, manifestLoadCallback, &loadData);
this->pub.info = infoNewLoad(read, cipherSpec, manifestLoadCallback, &loadData);
this->pub.data.backrestVersion = infoBackrestVersion(this->pub.info);
// Add the label to the reference list in case the manifest was created before 2.42 when the explicit reference list was

View File

@@ -37,8 +37,8 @@ typedef struct Manifest Manifest;
#include "command/backup/common.h"
#include "common/compress/helper.h"
#include "common/crypto/common.h"
#include "common/crypto/hash.h"
#include "common/crypto/spec.h"
#include "common/type/object.h"
#include "common/type/variant.h"
#include "info/info.h"
@@ -218,7 +218,7 @@ FN_EXTERN Manifest *manifestNewBuild(
const Pack *tablespaceList);
// Load a manifest from IO
FN_EXTERN Manifest *manifestNewLoad(IoRead *read);
FN_EXTERN Manifest *manifestNewLoad(IoRead *read, const CipherSpec *cipherSpec);
/***********************************************************************************************************************************
Getters/Setters
@@ -236,17 +236,17 @@ typedef struct ManifestPub
StringList *referenceList; // List of file references
} ManifestPub;
// Get/set the cipher subpassphrase
FN_INLINE_ALWAYS const String *
manifestCipherSubPass(const Manifest *const this)
// Get cipher spec for the files this manifest describes, set the pass they are encrypted with
FN_INLINE_ALWAYS const CipherSpec *
manifestCipherSpec(const Manifest *const this)
{
return infoCipherPass(THIS_PUB(Manifest)->info);
return infoCipherSpec(THIS_PUB(Manifest)->info);
}
FN_INLINE_ALWAYS void
manifestCipherSubPassSet(Manifest *const this, const String *const cipherSubPass)
manifestCipherSpecSet(Manifest *const this, const CipherSpec *const cipherSpec)
{
infoCipherPassSet(THIS_PUB(Manifest)->info, cipherSubPass);
infoCipherSpecSet(THIS_PUB(Manifest)->info, cipherSpec);
}
// Get manifest configuration and options
@@ -507,8 +507,7 @@ manifestFree(Manifest *const this)
Helper functions
***********************************************************************************************************************************/
// Load backup manifest
FN_EXTERN Manifest *manifestLoadFile(
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
FN_EXTERN Manifest *manifestLoadFile(const Storage *storage, const String *fileName, const CipherSpec *cipherSpec);
/***********************************************************************************************************************************
Macros for function logging

View File

@@ -1013,8 +1013,7 @@ typedef struct ManifestLoadFileData
MemContext *memContext; // Mem context
const Storage *storage; // Storage to load from
const String *fileName; // Base filename
CipherType cipherType; // Cipher type
const String *cipherPass; // Cipher passphrase
const CipherSpec *cipherSpec; // Cipher spec
Manifest *manifest; // Loaded manifest object
} ManifestLoadFileData;
@@ -1040,11 +1039,11 @@ manifestLoadFileCallback(void *const data, const unsigned int try)
// Attempt to load the file
IoRead *const read = storageReadIo(storageNewReadP(loadData->storage, fileName));
cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass);
cipherBlockFilterGroupAdd(ioReadFilterGroup(read), cipherModeDecrypt, loadData->cipherSpec);
MEM_CONTEXT_BEGIN(loadData->memContext)
{
loadData->manifest = manifestNewLoad(read);
loadData->manifest = manifestNewLoad(read, loadData->cipherSpec);
result = true;
}
MEM_CONTEXT_END();
@@ -1057,26 +1056,24 @@ manifestLoadFileCallback(void *const data, const unsigned int try)
FN_EXTERN Manifest *
manifestLoadFile(
const Storage *const storage, const String *const fileName, const CipherType cipherType, const String *const cipherPass)
const Storage *const storage, const String *const fileName, const CipherSpec *const cipherSpec)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(STRING_ID, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_PARAM(CIPHER_SPEC, cipherSpec);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
ASSERT(cipherSpec != NULL);
ManifestLoadFileData data =
{
.memContext = memContextCurrent(),
.storage = storage,
.fileName = fileName,
.cipherType = cipherType,
.cipherPass = cipherPass,
.cipherSpec = cipherSpec,
};
MEM_CONTEXT_TEMP_BEGIN()

View File

@@ -123,6 +123,7 @@ src_pgbackrest = [
'common/crypto/cipherBlock.c',
'common/crypto/common.c',
'common/crypto/hash.c',
'common/crypto/spec.c',
'common/crypto/xxhash.c',
'common/debug.c',
'common/encode.c',

View File

@@ -372,6 +372,7 @@ unit:
- common/crypto/common
- common/crypto/hash
- common/crypto/md5.vendor: included
- common/crypto/spec
- common/crypto/xxhash
# --------------------------------------------------------------------------------------------------------------------------------

View File

@@ -96,12 +96,12 @@ hrnBackupScriptSet(const HrnBackupScript *const script, const unsigned int scrip
/**********************************************************************************************************************************/
static void
backupProcess(const BackupData *const backupData, Manifest *const manifest, const String *const cipherPassBackup)
backupProcess(const BackupData *const backupData, Manifest *const manifest, const CipherSpec *const cipherSpecManifest)
{
FUNCTION_HARNESS_BEGIN();
FUNCTION_HARNESS_PARAM(BACKUP_DATA, backupData);
FUNCTION_HARNESS_PARAM(MANIFEST, manifest);
FUNCTION_HARNESS_PARAM(STRING, cipherPassBackup);
FUNCTION_HARNESS_PARAM(CIPHER_SPEC, cipherSpecManifest);
FUNCTION_HARNESS_END();
// If any file changes are scripted then make them
@@ -142,7 +142,7 @@ backupProcess(const BackupData *const backupData, Manifest *const manifest, cons
hrnBackupLocal.scriptSize = 0;
}
backupProcess_SHIMMED(backupData, manifest, cipherPassBackup);
backupProcess_SHIMMED(backupData, manifest, cipherSpecManifest);
FUNCTION_HARNESS_RETURN_VOID();
}
@@ -216,8 +216,8 @@ hrnBackupPqScript(const unsigned int pgVersion, const time_t backupTimeStart, Hr
if (!param.noPriorWal)
{
InfoArchive *infoArchive = infoArchiveLoadFile(
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, param.cipherType == 0 ? cipherTypeNone : param.cipherType,
param.cipherPass == NULL ? NULL : STR(param.cipherPass));
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR,
param.cipherSpecMain == NULL ? cipherSpecNewNone() : param.cipherSpecMain);
const String *archiveId = infoArchiveId(infoArchive);
StringList *walSegmentList = pgLsnRangeToWalSegmentList(
param.timeline, lsnStart - pgControl.walSegmentSize, param.noWal ? lsnStart - pgControl.walSegmentSize : lsnStop,
@@ -244,8 +244,7 @@ hrnBackupPqScript(const unsigned int pgVersion, const time_t backupTimeStart, Hr
// Encrypt with the archive passphrase, which is what archive-push writes WAL with
cipherBlockFilterGroupAdd(
ioWriteFilterGroup(storageWriteIo(write)), param.cipherType == 0 ? cipherTypeNone : param.cipherType,
cipherModeEncrypt, infoArchiveCipherPass(infoArchive));
ioWriteFilterGroup(storageWriteIo(write)), cipherModeEncrypt, infoArchiveCipherSpec(infoArchive));
storagePutP(write, walBuffer);
}

View File

@@ -47,8 +47,7 @@ typedef struct HrnBackupPqScriptParam
bool noArchiveCheck; // Do not check archive
bool walSwitch; // WAL switch is required
CompressType walCompressType; // Compress type for the archive files
CipherType cipherType; // Cipher type
const char *cipherPass; // Cipher pass
const CipherSpec *cipherSpecMain; // Cipher spec the repo is configured with
unsigned int walTotal; // Total WAL to write
unsigned int timeline; // Timeline to use for WAL files
const String *pgVersionForce; // PG version to use when control/catalog not found

View File

@@ -27,7 +27,7 @@ hrnBlockDeltaRender(const BlockMap *const blockMap, const size_t blockSize, cons
ASSERT(blockSize > 0);
String *const result = strNew();
BlockDelta *const blockDelta = blockDeltaNew(blockMap, blockSize, checksumSize, NULL, cipherTypeNone, NULL, compressTypeNone);
BlockDelta *const blockDelta = blockDeltaNew(blockMap, blockSize, checksumSize, NULL, cipherSpecNewNone(), compressTypeNone);
for (unsigned int readIdx = 0; readIdx < blockDeltaReadSize(blockDelta); readIdx++)
{

View File

@@ -17,6 +17,10 @@ Config option constants
#define TEST_CIPHER_PASS "xmainx"
#define TEST_CIPHER_PASS_ARCHIVE "xarchivex"
// Cipher spec for a test pass, defaulting to the main pass, since most tests encrypt with that
#define TEST_CIPHER_SPEC_PASS(pass) cipherSpecNew(cipherTypeAes256Cbc, BUFSTRZ(pass))
#define TEST_CIPHER_SPEC TEST_CIPHER_SPEC_PASS(TEST_CIPHER_PASS)
/***********************************************************************************************************************************
Load a test configuration

View File

@@ -82,8 +82,7 @@ static struct HrnHostLocal
StringId repoHost; // Host acting as repository
StringId storage; // Storage type
CompressType compressType; // Compress type
CipherType cipherType; // Cipher type
const String *cipherPass; // Cipher passphrase
const CipherSpec *cipherSpecMain; // Cipher spec the repo is configured with
unsigned int repoTotal; // Repository total
unsigned int restoreTotal; // Restore counter used to name spool path
bool tls; // Use TLS instead of SSH?
@@ -705,10 +704,10 @@ hrnHostConfig(HrnHost *const this)
strCatFmt(config, "repo1-path=%s\n", strZ(hrnHostRepo1Path(this)));
strCatZ(config, "repo1-retention-full=2\n");
if (hrnHostLocal.cipherType != cipherTypeNone)
if (cipherSpecType(hrnHostLocal.cipherSpecMain) != cipherTypeNone)
{
strCatFmt(config, "repo1-cipher-type=%s\n", zNewStrId(hrnHostLocal.cipherType));
strCatFmt(config, "repo1-cipher-pass=%s\n", strZ(hrnHostLocal.cipherPass));
strCatFmt(config, "repo1-cipher-type=%s\n", zNewStrId(cipherSpecType(hrnHostLocal.cipherSpecMain)));
strCatFmt(config, "repo1-cipher-pass=%s\n", strZ(strNewBuf(cipherSpecPass(hrnHostLocal.cipherSpecMain))));
}
if (hrnHostLocal.bundle)
@@ -1030,18 +1029,11 @@ hrnHostGet(const StringId id)
}
/**********************************************************************************************************************************/
CipherType
hrnHostCipherType(void)
const CipherSpec *
hrnHostCipherSpec(void)
{
FUNCTION_HARNESS_VOID();
FUNCTION_HARNESS_RETURN(STRING_ID, hrnHostLocal.cipherType);
}
const String *
hrnHostCipherPass(void)
{
FUNCTION_HARNESS_VOID();
FUNCTION_HARNESS_RETURN(UINT, hrnHostLocal.cipherPass);
FUNCTION_HARNESS_RETURN(CIPHER_SPEC, hrnHostLocal.cipherSpecMain);
}
CompressType
@@ -1235,8 +1227,8 @@ hrnHostBuild(const int line, const HrnHostTestDefine *const testMatrix, const si
hrnHostLocal.repoHost = strIdFromZ(testDef->repo);
hrnHostLocal.storage = strIdFromZ(testDef->stg);
hrnHostLocal.compressType = compressTypeEnum(strIdFromZ(testDef->cmp));
hrnHostLocal.cipherType = testDef->enc ? cipherTypeAes256Cbc : cipherTypeNone;
hrnHostLocal.cipherPass = testDef->enc ? strNewZ(HRN_CIPHER_PASSPHRASE) : NULL;
hrnHostLocal.cipherSpecMain =
testDef->enc ? cipherSpecNew(cipherTypeAes256Cbc, BUFSTRZ(HRN_CIPHER_PASSPHRASE)) : cipherSpecNewNone();
hrnHostLocal.repoTotal = testDef->rt;
hrnHostLocal.tls = testDef->tls;
hrnHostLocal.bundle = testDef->bnd;

View File

@@ -9,6 +9,7 @@ Object type
***********************************************************************************************************************************/
typedef struct HrnHost HrnHost;
#include "common/crypto/spec.h"
#include "common/type/object.h"
#include "common/type/string.h"
#include "postgres/client.h"
@@ -433,11 +434,8 @@ hrnHostSqlCommit(HrnHost *const this)
/***********************************************************************************************************************************
Helper functions
***********************************************************************************************************************************/
// Cipher Type
CipherType hrnHostCipherType(void);
// Cipher Passphrase
const String *hrnHostCipherPass(void);
// Cipher Spec
const CipherSpec *hrnHostCipherSpec(void);
// Compress Type
CompressType hrnHostCompressType(void);

View File

@@ -67,15 +67,13 @@ testStorageGet(const Storage *const storage, const char *const file, const char
IoFilterGroup *filterGroup = ioReadFilterGroup(storageReadIo(read));
// Add decrypt filter
if (param.cipherType != 0 && param.cipherType != cipherTypeNone)
if (param.cipherSpec != NULL && cipherSpecType(param.cipherSpec) != cipherTypeNone)
{
// Default to main cipher pass
if (param.cipherPass == NULL)
param.cipherPass = TEST_CIPHER_PASS;
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, param.cipherSpec));
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, param.cipherType, BUFSTRZ(param.cipherPass)));
strCatFmt(filter, "enc[%s,%s] ", zNewStrId(param.cipherType), param.cipherPass);
strCatFmt(
filter, "enc[%s,%s] ", zNewStrId(cipherSpecType(param.cipherSpec)),
strZ(strNewBuf(cipherSpecPass(param.cipherSpec))));
}
// Add decompress filter
@@ -394,14 +392,8 @@ hrnStoragePut(
}
// Add encrypted filter
if (param.cipherType != 0 && param.cipherType != cipherTypeNone)
{
// Default to main cipher pass
if (param.cipherPass == NULL)
param.cipherPass = TEST_CIPHER_PASS;
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, param.cipherType, BUFSTRZ(param.cipherPass)));
}
if (param.cipherSpec != NULL && cipherSpecType(param.cipherSpec) != cipherTypeNone)
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, param.cipherSpec));
// Add file name
printf(

View File

@@ -8,6 +8,7 @@ Helper functions for testing storage and related functions.
#include "common/compress/helper.h"
#include "common/crypto/common.h"
#include "common/crypto/spec.h"
#include "storage/storage.intern.h"
/***********************************************************************************************************************************
@@ -19,8 +20,7 @@ typedef struct TestStorageGetParam
bool remove; // Remove file after testing?
bool nullOnMissing; // NULL when file is missing
CompressType compressType; // Compression extension added to file name (limited gz and bz2)
CipherType cipherType;
const char *cipherPass; // If pass=null but cipherType set, defaults to TEST_CIPHER_PASS
const CipherSpec *cipherSpec; // Cipher spec the file is encrypted with
const char *comment; // Comment
} TestStorageGetParam;
@@ -202,8 +202,7 @@ typedef struct HrnStoragePutParam
mode_t modeFile; // File mode if not the default
time_t timeModified; // Time file was last modified
CompressType compressType; // Limited to gz and bz2 (lz4 and zstd are not always available)
CipherType cipherType;
const char *cipherPass;
const CipherSpec *cipherSpec; // Cipher spec to encrypt the file with
const char *comment; // Comment
} HrnStoragePutParam;

View File

@@ -1057,11 +1057,11 @@ testRun(void)
"\n"
"[db:history]\n"
"1={\"db-id\":" HRN_PG_SYSTEMID_10_Z ",\"db-version\":\"10\"}",
.cipherType = cipherTypeAes256Cbc);
.cipherSpec = TEST_CIPHER_SPEC);
HRN_STORAGE_PUT(
storageRepoWrite(), STORAGE_REPO_ARCHIVE "/10-1/01ABCDEF01ABCDEF01ABCDEF-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
buffer, .compressType = compressTypeGz, .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS_ARCHIVE);
buffer, .compressType = compressTypeGz, .cipherSpec = TEST_CIPHER_SPEC_PASS(TEST_CIPHER_PASS_ARCHIVE));
// Add encryption options
argList = strLstNew();

View File

@@ -179,8 +179,8 @@ testRun(void)
ArchivePushFileRepoData *repoData = lstGet(result.repoList, 0);
TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx");
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check archive id");
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check cipher type");
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check cipher pass (not set in this test)");
TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check cipher type");
TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check cipher pass (not set in this test)");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("mismatched repos when pg-path not present");
@@ -223,8 +223,8 @@ testRun(void)
repoData = lstGet(result.repoList, 0);
TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx");
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check archive id");
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check cipher type");
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check cipher pass (not set in this test)");
TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check cipher type");
TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check cipher pass (not set in this test)");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("matched repos when pg-path not present");
@@ -247,14 +247,14 @@ testRun(void)
repoData = lstGet(result.repoList, 0);
TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx");
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check repo2 archive id");
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check repo2 cipher pass");
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check repo2 cipher pass (not set in this test)");
TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check repo2 cipher pass");
TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check repo2 cipher pass (not set in this test)");
repoData = lstGet(result.repoList, 1);
TEST_RESULT_UINT(repoData->repoIdx, 1, "check repo idx");
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-2", "check repo4 archive id");
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check repo4 cipher type");
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check repo4 cipher pass (not set in this test)");
TEST_RESULT_UINT(cipherSpecType(repoData->cipherSpecArchive), cipherTypeNone, "check repo4 cipher type");
TEST_RESULT_PTR(cipherSpecPass(repoData->cipherSpecArchive), NULL, "check repo4 cipher pass (not set in this test)");
}
// *****************************************************************************************************************************
@@ -544,7 +544,7 @@ testRun(void)
"\n"
"[db:history]\n"
"1={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}",
.cipherType = cipherTypeAes256Cbc, .cipherPass = "badpassphrase");
.cipherSpec = TEST_CIPHER_SPEC_PASS("badpassphrase"));
// repo3 is not encrypted
HRN_INFO_PUT(

View File

@@ -27,8 +27,7 @@ Get a list of all files in the backup and a redacted version of the manifest tha
static String *
testBackupValidateFile(
const Storage *const storage, const String *const path, Manifest *const manifest, const ManifestData *const manifestData,
const String *const fileName, uint64_t fileSize, ManifestFilePack **const filePack, const CipherType cipherType,
const String *const cipherPass)
const String *const fileName, uint64_t fileSize, ManifestFilePack **const filePack)
{
FUNCTION_HARNESS_BEGIN();
FUNCTION_HARNESS_PARAM(STORAGE, storage);
@@ -38,13 +37,14 @@ testBackupValidateFile(
FUNCTION_HARNESS_PARAM(STRING, fileName);
FUNCTION_HARNESS_PARAM(UINT64, fileSize);
FUNCTION_HARNESS_PARAM_P(VOID, filePack);
FUNCTION_HARNESS_PARAM(STRING_ID, cipherType);
FUNCTION_HARNESS_PARAM(STRING, cipherPass);
FUNCTION_HARNESS_END();
String *const result = strNew();
ManifestFile file = manifestFileUnpack(manifest, *filePack);
// Every backup in a set shares the passphrase stored in the manifest, including files referenced from a prior backup
const CipherSpec *const cipherSpecBackup = manifestCipherSpec(manifest);
// Output name and size
// -------------------------------------------------------------------------------------------------------------
if (file.bundleId != 0)
@@ -89,11 +89,10 @@ testBackupValidateFile(
.offset = file.bundleOffset + file.sizeRepo - file.blockIncrMapSize,
.limit = VARUINT64(file.blockIncrMapSize));
if (cipherType != cipherTypeNone)
if (cipherSpecType(cipherSpecBackup) != cipherTypeNone)
{
ioFilterGroupAdd(
ioReadFilterGroup(storageReadIo(read)),
cipherBlockNewP(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), .raw = true));
ioReadFilterGroup(storageReadIo(read)), cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = true));
}
ioReadOpen(storageReadIo(read));
@@ -129,7 +128,7 @@ testBackupValidateFile(
bufUsedSet(fileBuffer, bufSize(fileBuffer));
BlockDelta *const blockDelta = blockDeltaNew(
blockMap, file.blockIncrSize, file.blockIncrChecksumSize, NULL, cipherType, cipherPass,
blockMap, file.blockIncrSize, file.blockIncrChecksumSize, NULL, cipherSpecBackup,
manifestData->backupOptionCompressType);
for (unsigned int readIdx = 0; readIdx < blockDeltaReadSize(blockDelta); readIdx++)
@@ -170,11 +169,10 @@ testBackupValidateFile(
.limit = VARUINT64(file.sizeRepo));
const bool raw = file.bundleId != 0 && manifest->pub.data.bundleRaw;
if (cipherType != cipherTypeNone)
if (cipherSpecType(cipherSpecBackup) != cipherTypeNone)
{
ioFilterGroupAdd(
ioReadFilterGroup(storageReadIo(read)),
cipherBlockNewP(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), .raw = raw));
ioReadFilterGroup(storageReadIo(read)), cipherBlockNewP(cipherModeDecrypt, cipherSpecBackup, .raw = raw));
}
if (manifestData->backupOptionCompressType != compressTypeNone)
@@ -255,7 +253,7 @@ testBackupValidateFile(
static String *
testBackupValidateList(
const Storage *const storage, const String *const path, Manifest *const manifest, const ManifestData *const manifestData,
StringList *const manifestFileList, const CipherType cipherType, const String *const cipherPass, String *const result)
StringList *const manifestFileList, String *const result)
{
FUNCTION_HARNESS_BEGIN();
FUNCTION_HARNESS_PARAM(STORAGE, storage);
@@ -263,8 +261,6 @@ testBackupValidateList(
FUNCTION_HARNESS_PARAM(MANIFEST, manifest);
FUNCTION_HARNESS_PARAM_P(VOID, manifestData);
FUNCTION_HARNESS_PARAM(STRING_LIST, manifestFileList);
FUNCTION_HARNESS_PARAM(STRING_ID, cipherType);
FUNCTION_HARNESS_PARAM(STRING, cipherPass);
FUNCTION_HARNESS_PARAM(STRING, result);
FUNCTION_HARNESS_END();
@@ -353,10 +349,7 @@ testBackupValidateList(
manifestFileList, (String *const)*filePack, .required = true);
strLstRemoveIdx(manifestFileList, manifestFileIdx);
strCat(
result,
testBackupValidateFile(
storage, path, manifest, manifestData, info.name, info.size, filePack, cipherType, cipherPass));
strCat(result, testBackupValidateFile(storage, path, manifest, manifestData, info.name, info.size, filePack));
}
break;
@@ -402,8 +395,7 @@ testBackupValidateList(
typedef struct TestBackupValidateParam
{
VAR_PARAM_HEADER;
CipherType cipherType; // Cipher type
const char *cipherPass; // Cipher pass
const CipherSpec *cipherSpecMain; // Cipher spec the repo is configured with
} TestBackupValidateParam;
#define testBackupValidateP(storage, path, ...) \
@@ -415,8 +407,7 @@ testBackupValidate(const Storage *const storage, const String *const path, const
FUNCTION_HARNESS_BEGIN();
FUNCTION_HARNESS_PARAM(STORAGE, storage);
FUNCTION_HARNESS_PARAM(STRING, path);
FUNCTION_HARNESS_PARAM(UINT64, param.cipherType);
FUNCTION_HARNESS_PARAM(STRINGZ, param.cipherPass);
FUNCTION_HARNESS_PARAM(CIPHER_SPEC, param.cipherSpecMain);
FUNCTION_HARNESS_END();
ASSERT(storage != NULL);
@@ -429,11 +420,9 @@ testBackupValidate(const Storage *const storage, const String *const path, const
// Build a list of files in the backup path and verify against the manifest
// -------------------------------------------------------------------------------------------------------------------------
const InfoBackup *const infoBackup = infoBackupLoadFile(
storageRepo(), INFO_BACKUP_PATH_FILE_STR, param.cipherType == 0 ? cipherTypeNone : param.cipherType,
param.cipherPass == NULL ? NULL : STR(param.cipherPass));
storageRepo(), INFO_BACKUP_PATH_FILE_STR, param.cipherSpecMain == NULL ? cipherSpecNewNone() : param.cipherSpecMain);
Manifest *manifest = manifestLoadFile(
storage, strNewFmt("%s/" BACKUP_MANIFEST_FILE, strZ(path)), param.cipherType == 0 ? cipherTypeNone : param.cipherType,
param.cipherPass == NULL ? NULL : infoBackupCipherPass(infoBackup));
storage, strNewFmt("%s/" BACKUP_MANIFEST_FILE, strZ(path)), infoBackupCipherSpec(infoBackup));
// Build list of files in the manifest
StringList *const manifestFileList = strLstNew();
@@ -442,10 +431,7 @@ testBackupValidate(const Storage *const storage, const String *const path, const
strLstAdd(manifestFileList, manifestFileUnpack(manifest, manifestFilePackGet(manifest, fileIdx)).name);
// Validate files on disk against the manifest
const CipherType cipherType = param.cipherType == 0 ? cipherTypeNone : param.cipherType;
const String *const cipherPass = param.cipherPass == NULL ? NULL : manifestCipherSubPass(manifest);
testBackupValidateList(storage, path, manifest, manifestData(manifest), manifestFileList, cipherType, cipherPass, result);
testBackupValidateList(storage, path, manifest, manifestData(manifest), manifestFileList, result);
// Check remaining files in the manifest -- these should all be references
for (unsigned int manifestFileIdx = 0; manifestFileIdx < strLstSize(manifestFileList); manifestFileIdx++)
@@ -473,7 +459,7 @@ testBackupValidate(const Storage *const storage, const String *const path, const
.compressType = manifestData(manifest)->backupOptionCompressType,
.blockIncr = file.blockIncrMapSize != 0),
sizeof(STORAGE_REPO_BACKUP)),
file.sizeRepo, filePack, cipherType, cipherPass));
file.sizeRepo, filePack));
}
// Make sure both backup.manifest files exist since we skipped them in the callback above
@@ -1326,7 +1312,8 @@ testRun(void)
ioFilterParamList(
blockIncrNew(
3, 3, 8, 2, 4, 5, NULL, compressFilterP(compressTypeGz, 1, .raw = true),
cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS), .raw = true)))),
cipherBlockNewP(
cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS)), .raw = true)))),
"block incr pack");
}
@@ -1690,7 +1677,7 @@ testRun(void)
HRN_STORAGE_PATH_CREATE(storageRepoWrite(), STORAGE_REPO_BACKUP "/20191003-105320F");
TEST_RESULT_PTR(backupResumeFind((Manifest *)1, NULL), NULL, "find resumable backup");
TEST_RESULT_PTR(backupResumeFind((Manifest *)1, cipherSpecNewNone()), NULL, "find resumable backup");
TEST_RESULT_LOG(
"P00 WARN: backup '20191003-105320F' cannot be resumed: partially deleted by prior resume or invalid");
@@ -1704,7 +1691,7 @@ testRun(void)
HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT);
TEST_RESULT_PTR(backupResumeFind((Manifest *)1, NULL), NULL, "find resumable backup");
TEST_RESULT_PTR(backupResumeFind((Manifest *)1, cipherSpecNewNone()), NULL, "find resumable backup");
TEST_RESULT_LOG("P00 INFO: backup '20191003-105320F' cannot be resumed: resume is disabled");
@@ -1727,7 +1714,7 @@ testRun(void)
HRN_STORAGE_PUT_Z(storageRepoWrite(), STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, "X");
TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup");
TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup");
TEST_RESULT_LOG(
"P00 WARN: backup '20191003-105320F' cannot be resumed: unable to read"
@@ -1759,7 +1746,7 @@ testRun(void)
storageNewWriteP(
storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT))));
TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup");
TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup");
TEST_RESULT_LOG(
"P00 WARN: backup '20191003-105320F' cannot be resumed:"
@@ -1781,7 +1768,7 @@ testRun(void)
storageNewWriteP(
storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT))));
TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup");
TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup");
TEST_RESULT_LOG(
"P00 WARN: backup '20191003-105320F' cannot be resumed:"
@@ -1803,7 +1790,7 @@ testRun(void)
storageNewWriteP(
storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT))));
TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup");
TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup");
TEST_RESULT_LOG(
"P00 WARN: backup '20191003-105320F' cannot be resumed:"
@@ -1824,7 +1811,7 @@ testRun(void)
storageNewWriteP(
storageRepoWrite(), STRDEF(STORAGE_REPO_BACKUP "/20191003-105320F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT))));
TEST_RESULT_PTR(backupResumeFind(manifest, NULL), NULL, "find resumable backup");
TEST_RESULT_PTR(backupResumeFind(manifest, cipherSpecNewNone()), NULL, "find resumable backup");
TEST_RESULT_LOG(
"P00 WARN: backup '20191003-105320F' cannot be resumed:"
@@ -3663,7 +3650,8 @@ testRun(void)
{
// Load the previous manifest and null out the checksum-page option to be sure it gets set to false in this backup
const String *manifestPriorFile = STRDEF(STORAGE_REPO_BACKUP "/20191103-165320F/" BACKUP_MANIFEST_FILE);
Manifest *manifestPrior = manifestNewLoad(storageReadIo(storageNewReadP(storageRepo(), manifestPriorFile)));
Manifest *manifestPrior = manifestNewLoad(
storageReadIo(storageNewReadP(storageRepo(), manifestPriorFile)), cipherSpecNewNone());
manifestPrior->pub.data.backupOptionChecksumPage = NULL;
manifestSave(manifestPrior, storageWriteIo(storageNewWriteP(storageRepoWrite(), manifestPriorFile)));
@@ -3853,8 +3841,8 @@ testRun(void)
// Run backup
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true);
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC,
.walTotal = 2, .walSwitch = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@@ -3874,8 +3862,7 @@ testRun(void)
TEST_RESULT_STR_Z(
testBackupValidateP(
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS),
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC),
".> {d=20191108-080000F}\n"
"bundle/1/pg_data/PG_VERSION {s=2, ts=-400000}\n"
"bundle/1/pg_data/global/pg_control {s=8192}\n"
@@ -3932,8 +3919,8 @@ testRun(void)
// Run backup
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true);
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC,
.walTotal = 2, .walSwitch = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@@ -3960,8 +3947,7 @@ testRun(void)
TEST_RESULT_STR_Z(
testBackupValidateP(
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS),
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC),
".> {d=20191108-080000F}\n"
"bundle/1/pg_data/PG_VERSION {s=2, ts=-500000}\n"
"bundle/1/pg_data/global/pg_control {s=8192}\n"
@@ -4029,8 +4015,8 @@ testRun(void)
// Run backup
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true);
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC,
.walTotal = 2, .walSwitch = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@@ -4058,8 +4044,7 @@ testRun(void)
TEST_RESULT_STR_Z(
testBackupValidateP(
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS),
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC),
".> {d=20191108-080000F_20191110-153320D}\n"
"bundle/1/pg_data/block-age-multiplier {s=32768, m=1:{0,1}, ts=-86400}\n"
"bundle/1/pg_data/block-age-to-zero {s=16384, ts=-172800}\n"
@@ -4095,8 +4080,8 @@ testRun(void)
// Run backup
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS, .walTotal = 1, .walSwitch = false);
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC,
.walTotal = 1, .walSwitch = false);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
@@ -4121,8 +4106,7 @@ testRun(void)
TEST_RESULT_STR_Z(
testBackupValidateP(
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS),
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC),
".> {d=20191108-080000F_20191111-052640I}\n"
"pg_data/backup_label.gz {s=17, ts=+2}\n"
"pg_data/global/pg_control.gz {s=8192}\n"
@@ -4186,8 +4170,8 @@ testRun(void)
{.op = hrnBackupScriptOpUpdate, .file = storagePathP(storagePg(), STRDEF("global/1")),
.time = backupTimeStart + 1, .content = fileGrow});
hrnBackupPqScriptP(
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS, .walTotal = 2, .walSwitch = true);
PG_VERSION_11, backupTimeStart, .walCompressType = compressTypeNone, .cipherSpecMain = TEST_CIPHER_SPEC,
.walTotal = 2, .walSwitch = true);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
// Make sure that global/1 grew as expected but the extra bytes were not copied
@@ -4211,8 +4195,7 @@ testRun(void)
TEST_RESULT_STR_Z(
testBackupValidateP(
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS),
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"), .cipherSpecMain = TEST_CIPHER_SPEC),
".> {d=20191111-192000F}\n"
"bundle/1/pg_data/PG_VERSION {s=2}\n"
"bundle/1/pg_data/global/pg_control {s=8192}\n"

View File

@@ -753,10 +753,7 @@ testRun(void)
// Version mismatch
TEST_ERROR(
checkStanzaInfoPg(
storageRepoIdx(0), PG_VERSION_18, HRN_PG_SYSTEMID_18, cfgOptionIdxStrId(cfgOptRepoCipherType, 0),
cfgOptionIdxStr(cfgOptRepoCipherPass, 0)),
FileInvalidError,
checkStanzaInfoPg(storageRepoIdx(0), PG_VERSION_18, HRN_PG_SYSTEMID_18, cfgCipherSpecMainIdx(0)), FileInvalidError,
"backup and archive info files exist but do not match the database\n"
"HINT: is this the correct stanza?\n"
"HINT: did an error occur during stanza-upgrade?");
@@ -766,10 +763,7 @@ testRun(void)
// SystemId mismatch
TEST_ERROR(
checkStanzaInfoPg(
storageRepoIdx(0), PG_VERSION_96, 6569239123849665699, cfgOptionIdxStrId(cfgOptRepoCipherType, 0),
cfgOptionIdxStr(cfgOptRepoCipherPass, 0)),
FileInvalidError,
checkStanzaInfoPg(storageRepoIdx(0), PG_VERSION_96, 6569239123849665699, cfgCipherSpecMainIdx(0)), FileInvalidError,
"backup and archive info files exist but do not match the database\n"
"HINT: is this the correct stanza?\n"
"HINT: did an error occur during stanza-upgrade?");

View File

@@ -156,7 +156,7 @@ testRun(void)
// Create backup.info
InfoBackup *infoBackup = NULL;
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info");
// Load Parameters
StringList *argList = strLstDup(argListAvoidWarn);
@@ -190,7 +190,7 @@ testRun(void)
{
// Create backup.info
InfoBackup *infoBackup = NULL;
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("retention-full not set - nothing expired");
@@ -251,7 +251,7 @@ testRun(void)
{
// Create backup.info
InfoBackup *infoBackup = NULL;
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("retention-diff not set - nothing expired");
@@ -334,7 +334,7 @@ testRun(void)
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702"
",\"db-version\":\"9.4\"}");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent), cipherSpecNewNone()), "get backup.info");
// Load parameters
argList = strLstDup(argListAvoidWarn);
@@ -386,7 +386,8 @@ testRun(void)
InfoBackup *infoBackup = NULL;
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
// Put some files in the backup directories
HRN_STORAGE_PUT_Z(storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152100F/" BOGUS_STR, BOGUS_STR);
@@ -429,7 +430,7 @@ testRun(void)
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702"
",\"db-version\":\"9.4\"}");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent), cipherSpecNewNone()), "get backup.info");
TEST_RESULT_VOID(removeExpiredBackup(infoBackup, NULL, 0), "remove backups - backup.info current empty");
@@ -477,7 +478,8 @@ testRun(void)
",\"db-version\":\"9.4\"}");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
// Committed backup (in backup.info) and an older orphan backup that is not in backup.info and has no manifest copy
HRN_STORAGE_PUT_Z(storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152138F/" BOGUS_STR, BOGUS_STR);
@@ -537,7 +539,7 @@ testRun(void)
",\"db-version\":\"9.4\"}");
InfoBackup *infoBackup = NULL;
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent), cipherSpecNewNone()), "get backup.info");
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false, 0), "archive retention not set");
TEST_RESULT_LOG(
@@ -644,7 +646,8 @@ testRun(void)
",\"db-version\":\"10\"}\n");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE,
@@ -885,13 +888,13 @@ testRun(void)
"archive sub path repo1 not removed");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info repo2");
TEST_RESULT_BOOL(
strLstExists(infoBackupDataLabelList(infoBackup, NULL), STRDEF("20181119-152138F")), false,
"backup removed from repo2");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup, infoBackupLoadFile(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info repo1");
TEST_RESULT_BOOL(
strLstExists(infoBackupDataLabelList(infoBackup, NULL), STRDEF("20181119-152138F")), true, "backup exists repo1");
@@ -1125,7 +1128,7 @@ testRun(void)
"P00 INFO: repo2: 10-2 no archive to remove");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"repo1: get backup.info");
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "repo1: backup.info updated on disk");
TEST_RESULT_STRLST_Z(
@@ -1133,7 +1136,7 @@ testRun(void)
"20181119-152900F\n20181119-152900F_20181119-152500I\n", "repo1: remaining current backups correct");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"repo2: get backup.info");
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 4, "repo2: backup.info updated on disk");
TEST_RESULT_STRLST_Z(
@@ -1256,7 +1259,8 @@ testRun(void)
",\"db-version\":\"10\"}\n");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
archiveGenerate(storageRepoWrite(), STORAGE_REPO_ARCHIVE, 1, 5, "9.4-1", "0000000100000000");
@@ -1338,7 +1342,8 @@ testRun(void)
",\"db-version\":\"10\"}\n");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152138F/" BACKUP_MANIFEST_FILE);
@@ -1601,7 +1606,8 @@ testRun(void)
",\"db-version\":\"10\"}\n");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE,
@@ -1669,7 +1675,8 @@ testRun(void)
",\"db-version\":\"10\"}\n");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
archiveGenerate(storageRepoWrite(), STORAGE_REPO_ARCHIVE, 1, 10, "9.4-1", "0000000100000000");
@@ -2064,7 +2071,8 @@ testRun(void)
InfoBackup *infoBackup = NULL;
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
// Create "latest" symlink
const String *latestLink = storagePathP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest"));
@@ -2302,7 +2310,8 @@ testRun(void)
// Load the backup info. Do not store a manifest file for the adhoc backup for code coverage
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL), "get backup.info");
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get backup.info");
HRN_STORAGE_PATH_CREATE(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152850F_20181119-152252D",
@@ -2451,7 +2460,7 @@ testRun(void)
"[db:history]\n"
"1={\"db-id\":6625592122879095702,\"db-version\":\"9.4\"}\n"
"2={\"db-id\":6626363367545678089,\"db-version\":\"12\"}",
.cipherType = cipherTypeAes256Cbc);
.cipherSpec = TEST_CIPHER_SPEC);
const String *backupInfoContent = STRDEF(
TEST_BACKUP_CURRENT
@@ -2460,16 +2469,16 @@ testRun(void)
"cipher-pass=\"somepass\"\n"
TEST_BACKUP_DB);
HRN_INFO_PUT(storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, strZ(backupInfoContent), .cipherType = cipherTypeAes256Cbc);
HRN_INFO_PUT(storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, strZ(backupInfoContent), .cipherSpec = TEST_CIPHER_SPEC);
HRN_INFO_PUT(
storageRepoIdxWrite(1), STORAGE_REPO_BACKUP "/20181119-152850F/" BACKUP_MANIFEST_FILE,
"[backup]\nbackup-type=\"full\"\n", .cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass");
"[backup]\nbackup-type=\"full\"\n", .cipherSpec = TEST_CIPHER_SPEC_PASS("somepass"));
HRN_INFO_PUT(
storageRepoIdxWrite(1), STORAGE_REPO_BACKUP "/20181119-152850F_20181119-152252D/" BACKUP_MANIFEST_FILE,
"[backup]\nbackup-type=\"diff\"\n", .cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass");
"[backup]\nbackup-type=\"diff\"\n", .cipherSpec = TEST_CIPHER_SPEC_PASS("somepass"));
HRN_INFO_PUT(
storageRepoIdxWrite(1), STORAGE_REPO_BACKUP "/20181119-152850F_20181200-152252D/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
strZ(manifestContent), .cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass", .comment = "resumable backup");
strZ(manifestContent), .cipherSpec = TEST_CIPHER_SPEC_PASS("somepass"), .comment = "resumable backup");
// archives to repo2
archiveGenerate(storageRepoIdxWrite(1), STORAGE_REPO_ARCHIVE, 2, 10, "12-2", "0000000100000000");
@@ -2530,7 +2539,7 @@ testRun(void)
"\n"
"[db:history]\n"
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702"
",\"db-version\":\"9.4\"}"))),
",\"db-version\":\"9.4\"}")), cipherSpecNewNone()),
"empty backup.info");
TEST_RESULT_UINT(expireTimeBasedBackup(infoBackup, (time_t)(timeNow - (40 * SEC_PER_DAY)), 0), 0, "no backups to expire");
@@ -2569,7 +2578,7 @@ testRun(void)
// Set the log level to detail so archive expiration messages are seen
harnessLogLevelSet(logLevelDetail);
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase), cipherSpecNewNone()), "get backup.info");
TEST_RESULT_VOID(cmdExpire(), "repo-retention-full not set for time-based");
TEST_RESULT_LOG(
"P00 WARN: option 'repo1-retention-full' is not set for 'repo1-retention-full-type=time', the repository may run out"
@@ -2712,7 +2721,7 @@ testRun(void)
// Expire oldest from backup.info only, leaving the backup and archives on disk then save backup.info without oldest backup
TEST_RESULT_UINT(expireTimeBasedBackup(infoBackup, (time_t)(timeNow - (25 * SEC_PER_DAY)), 0), 1, "expire oldest backup");
TEST_RESULT_VOID(
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"save backup.info without oldest");
TEST_RESULT_LOG("P00 INFO: repo1: expire time-based backup 20181119-152138F");
TEST_RESULT_VOID(cmdExpire(), "only oldest backup expired");

View File

@@ -1045,7 +1045,7 @@ testRun(void)
"\n"
"[db:history]\n"
"1={\"db-id\":6626363367545678089,\"db-version\":\"9.5\"}\n",
.cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS,
.cipherSpec = TEST_CIPHER_SPEC,
.comment = "write encrypted archive.info, stanza1, repo2");
HRN_INFO_PUT(
storageTest, TEST_PATH "/repo2/" STORAGE_PATH_BACKUP "/stanza1/" INFO_BACKUP_FILE,
@@ -1072,7 +1072,7 @@ testRun(void)
"[db:history]\n"
"1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6626363367545678089"
",\"db-version\":\"9.5\"}\n",
.cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS,
.cipherSpec = TEST_CIPHER_SPEC,
.comment = "write encrypted backup.info, stanza1, repo2");
// Add WAL on repo1 and encrypted repo2 for stanza1
@@ -1143,7 +1143,7 @@ testRun(void)
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
.cipherType = cipherTypeAes256Cbc, .cipherPass = "somepass",
.cipherSpec = TEST_CIPHER_SPEC_PASS("somepass"),
.comment = "write encrypted manifest, stanza1, repo2");
// Create a stanza on repo2 that is not on repo1
@@ -1159,7 +1159,7 @@ testRun(void)
"\n"
"[db:history]\n"
"1={\"db-id\":6626363367545678089,\"db-version\":\"9.4\"}\n",
.cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS,
.cipherSpec = TEST_CIPHER_SPEC,
.comment = "write encrypted archive.info, repo2, stanza3");
HRN_INFO_PUT(
storageTest, TEST_PATH "/repo2/" STORAGE_PATH_BACKUP "/stanza3/" INFO_BACKUP_FILE,
@@ -1185,7 +1185,7 @@ testRun(void)
"[db:history]\n"
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6626363367545678089"
",\"db-version\":\"9.4\"}\n",
.cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS,
.cipherSpec = TEST_CIPHER_SPEC,
.comment = "write encrypted backup.info, repo2, stanza3");
// Store some WAL in stanza on repo2 that is not on repo1
@@ -3069,7 +3069,7 @@ testRun(void)
"[db:history]\n"
"1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6626363367545678089"
",\"db-version\":\"9.5\"}\n",
.cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS,
.cipherSpec = TEST_CIPHER_SPEC,
.comment = "backup.info without current, repo2, stanza1");
TEST_RESULT_STR_Z(

View File

@@ -108,8 +108,7 @@ testRun(void)
HRN_CFG_LOAD(cfgCmdBackup, argList);
hrnBackupPqScriptP(
PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS);
PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherSpecMain = TEST_CIPHER_SPEC);
TEST_RESULT_VOID(hrnCmdBackup(), "backup repo2");
}
@@ -137,7 +136,7 @@ testRun(void)
// Munge the pg_control checksum since it will vary by architecture
Manifest *manifest = manifestLoadFile(
storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/20191002-070640F_20191003-105320D/" BACKUP_MANIFEST_FILE),
cipherTypeNone, NULL);
cipherSpecNewNone());
ManifestFile file = manifestFileFind(manifest, STRDEF(MANIFEST_TARGET_PGDATA "/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL));
file.checksumSha1 = bufPtr(bufNewDecode(encodingHex, STRDEF("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")));
@@ -155,8 +154,7 @@ testRun(void)
HRN_CFG_LOAD(cfgCmdBackup, argList);
hrnBackupPqScriptP(
PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherType = cipherTypeAes256Cbc,
.cipherPass = TEST_CIPHER_PASS);
PG_VERSION_14, backupTimeStart, .noArchiveCheck = true, .noWal = true, .cipherSpecMain = TEST_CIPHER_SPEC);
TEST_RESULT_VOID(hrnCmdBackup(), "backup repo2");
}

View File

@@ -402,31 +402,30 @@ testRun(void)
HRN_STORAGE_PUT(storageFixture, strZ(fileName), fileBuffer);
HRN_STORAGE_PUT_Z(storageFixture, strZ(fileRawName), fileRawContent);
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_ARCHIVE "/test/" INFO_ARCHIVE_FILE, archiveInfoFileBuffer,
.cipherType = cipherTypeAes256Cbc);
storageFixture, STORAGE_PATH_ARCHIVE "/test/" INFO_ARCHIVE_FILE, archiveInfoFileBuffer, .cipherSpec = TEST_CIPHER_SPEC);
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_ARCHIVE "/test/" INFO_ARCHIVE_FILE ".copy", archiveInfoFileBuffer,
.cipherType = cipherTypeAes256Cbc);
.cipherSpec = TEST_CIPHER_SPEC);
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_BACKUP "/test/" INFO_BACKUP_FILE, backupInfoFileBuffer, .cipherType = cipherTypeAes256Cbc);
storageFixture, STORAGE_PATH_BACKUP "/test/" INFO_BACKUP_FILE, backupInfoFileBuffer, .cipherSpec = TEST_CIPHER_SPEC);
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_BACKUP "/test/" INFO_BACKUP_FILE ".copy", backupInfoFileBuffer,
.cipherType = cipherTypeAes256Cbc);
.cipherSpec = TEST_CIPHER_SPEC);
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_ARCHIVE "/test/12-1/000000010000000100000001-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
archiveFileBuffer, .cipherType = cipherTypeAes256Cbc, .cipherPass = "custom");
archiveFileBuffer, .cipherSpec = TEST_CIPHER_SPEC_PASS("custom"));
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_BACKUP "/test/latest/" BACKUP_MANIFEST_FILE, manifestFileBuffer,
.cipherType = cipherTypeAes256Cbc, .cipherPass = "custom");
.cipherSpec = TEST_CIPHER_SPEC_PASS("custom"));
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_BACKUP "/test/latest/" BACKUP_MANIFEST_FILE ".copy", manifestFileBuffer,
.cipherType = cipherTypeAes256Cbc, .cipherPass = "custom");
.cipherSpec = TEST_CIPHER_SPEC_PASS("custom"));
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_BACKUP "/test/backup.history/2020/label.manifest.gz", manifestFileBuffer,
.cipherType = cipherTypeAes256Cbc, .cipherPass = "custom");
.cipherSpec = TEST_CIPHER_SPEC_PASS("custom"));
HRN_STORAGE_PUT(
storageFixture, STORAGE_PATH_BACKUP "/test/latest/pg_data/backup_label", backupLabelBuffer,
.cipherType = cipherTypeAes256Cbc, .cipherPass = "custom2");
.cipherSpec = TEST_CIPHER_SPEC_PASS("custom2"));
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("error when missing source");

View File

@@ -236,7 +236,7 @@ testRun(void)
ioBufferReadNewOpen(BUF(bufPtr(destination) + (bufUsed(destination) - (size_t)mapSize), (size_t)mapSize)), 3, 5);
// Perform block delta
BlockDelta *blockDelta = blockDeltaNew(blockMap, 3, 5, NULL, cipherTypeNone, NULL, compressTypeGz);
BlockDelta *blockDelta = blockDeltaNew(blockMap, 3, 5, NULL, cipherSpecNewNone(), compressTypeGz);
const BlockDeltaRead *blockDeltaRead = blockDeltaReadGet(blockDelta, 0);
IoRead *read = ioBufferReadNewOpen(destination);
@@ -289,7 +289,7 @@ testRun(void)
HRN_STORAGE_PUT_Z(
storageRepoWrite(), zNewFmt(STORAGE_REPO_BACKUP "/%s/%s", strZ(repoFileReferenceFull), strZ(repoFile1)),
"acefile", .compressType = compressTypeGz, .cipherType = cipherTypeAes256Cbc, .cipherPass = "badpass",
"acefile", .compressType = compressTypeGz, .cipherSpec = TEST_CIPHER_SPEC_PASS("badpass"),
.comment = "create a compressed encrypted repo file");
List *fileList = lstNewP(sizeof(RestoreFile));
@@ -311,7 +311,7 @@ testRun(void)
TEST_ERROR(
restoreFile(
strNewFmt(STORAGE_REPO_BACKUP "/%s/%s.gz", strZ(repoFileReferenceFull), strZ(repoFile1)), repoIdx, compressTypeGz,
0, false, false, false, STRDEF("badpass"), NULL, fileList),
0, false, false, false, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("badpass")), NULL, fileList),
ChecksumError,
"error restoring 'normal': actual checksum 'd1cd8a7d11daa26814b93eb604e1d49ab4b43770' does not match expected checksum"
" 'ffffffffffffffffffffffffffffffffffffffff'");
@@ -2070,45 +2070,45 @@ testRun(void)
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_11, 1, 0xA1, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT, cipherTypeNone,
NULL),
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_11, 1, 0xA1, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherSpecNewNone()),
"follow current timeline because of version");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_11, 1, 0xA1, STRDEF("latest"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"follow latest timeline as requested");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, NULL, cipherTypeNone, CFGOPTVAL_RESTORE_TYPE_DEFAULT,
NULL),
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherSpecNewNone()),
"follow latest timeline because of version");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, STRDEF("current"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"follow current timeline as requested");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 1, 0xA1, STRDEF("1"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"follow requested timeline (same as current)");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 0x10, 0xA1, STRDEF("0x10"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"follow requested hex timeline (same as current)");
TEST_ERROR(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 0x10, 0xA1, STRDEF("bogus"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
DbMismatchError, "invalid target timeline 'bogus'");
HRN_STORAGE_PUT_Z(storageTest, "repo/archive/test1/17-1/00000009.history", "8");
TEST_ERROR(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 8, 0xA1, STRDEF("9"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
FormatError,
"invalid timeline '9' at '" TEST_PATH "/repo/archive/test1/17-1/00000009.history':"
" invalid history line format '8'");
@@ -2121,27 +2121,27 @@ testRun(void)
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 10, 0x4FFFFFF, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"follow current timeline");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x4FFFFFF, NULL, CFGOPTVAL_RESTORE_TYPE_IMMEDIATE,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"follow current timeline (based on type immediate)");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x4FFFFFF, NULL, CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"follow latest timeline");
TEST_RESULT_VOID(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x4FFFFFF, STRDEF("10"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
"target timeline found");
TEST_ERROR(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 9, 0x6000000, STRDEF("10"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
DbMismatchError,
"target timeline A forked from backup timeline 9 at 0/5000000 which is before backup lsn of 0/6000000\n"
"HINT: was the target timeline created by accidentally promoting a standby?\n"
@@ -2155,7 +2155,7 @@ testRun(void)
TEST_ERROR(
timelineVerify(
storageRepoIdx(0), STRDEF("17-1"), PG_VERSION_12, 6, 0x4FFFFFF, STRDEF("11"), CFGOPTVAL_RESTORE_TYPE_DEFAULT,
cipherTypeNone, NULL),
cipherSpecNewNone()),
DbMismatchError, "backup timeline 6, lsn 0/4ffffff is not in the history of target timeline B\n"
"HINT: was the target timeline created by promoting from a timeline < latest?");
}
@@ -2287,7 +2287,7 @@ testRun(void)
// Store the file also to the encrypted repo
HRN_STORAGE_PUT_Z(
storageRepoIdxWrite(1), TEST_REPO_PATH PG_FILE_PGVERSION, PG_VERSION_11_Z "\n",
.cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS_ARCHIVE);
.cipherSpec = TEST_CIPHER_SPEC_PASS(TEST_CIPHER_PASS_ARCHIVE));
// pg_tblspc
HRN_MANIFEST_PATH_ADD(manifest, .name = MANIFEST_TARGET_PGDATA "/" MANIFEST_TARGET_PGTBLSPC);
@@ -2307,8 +2307,9 @@ testRun(void)
// Read the manifest, set a cipher passphrase and store it to the encrypted repo
Manifest *manifestEncrypted = manifestLoadFile(
storageRepoIdxWrite(0), STRDEF(STORAGE_REPO_BACKUP "/" TEST_LABEL "/" BACKUP_MANIFEST_FILE), cipherTypeNone, NULL);
manifestCipherSubPassSet(manifestEncrypted, STRDEF(TEST_CIPHER_PASS_ARCHIVE));
storageRepoIdxWrite(0), STRDEF(STORAGE_REPO_BACKUP "/" TEST_LABEL "/" BACKUP_MANIFEST_FILE),
cipherSpecNewNone());
manifestCipherSpecSet(manifestEncrypted, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS_ARCHIVE)));
// Open file for write
IoWrite *write = storageWriteIo(
@@ -2319,19 +2320,21 @@ testRun(void)
// Add encryption filter and save the encrypted manifest
#define TEST_CIPHER_PASS_MANIFEST "backpass"
cipherBlockFilterGroupAdd(
ioWriteFilterGroup(write), cfgOptionIdxStrId(cfgOptRepoCipherType, 1), cipherModeEncrypt,
STRDEF(TEST_CIPHER_PASS_MANIFEST));
ioWriteFilterGroup(write), cipherModeEncrypt,
cipherSpecNew(cfgOptionIdxStrId(cfgOptRepoCipherType, 1), BUFSTRDEF(TEST_CIPHER_PASS_MANIFEST)));
manifestSave(manifestEncrypted, write);
// Write backup.info to the encrypted repo
HRN_INFO_PUT(
storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, TEST_RESTORE_BACKUP_INFO "\n[cipher]\ncipher-pass=\""
TEST_CIPHER_PASS_MANIFEST "\"\n\n" TEST_RESTORE_BACKUP_INFO_DB, .cipherType = cipherTypeAes256Cbc);
TEST_CIPHER_PASS_MANIFEST "\"\n\n" TEST_RESTORE_BACKUP_INFO_DB, .cipherSpec = TEST_CIPHER_SPEC);
// Write archive.info to the encrypted repo
InfoArchive *infoArchive = infoArchiveNew(PG_VERSION_11, 6569239123849665679, STRDEF(TEST_CIPHER_PASS_ARCHIVE));
InfoArchive *infoArchive = infoArchiveNew(
PG_VERSION_11, 6569239123849665679, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS_ARCHIVE)));
infoArchiveSaveFile(
infoArchive, storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF(TEST_CIPHER_PASS));
infoArchive, storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE_STR,
cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_CIPHER_PASS)));
TEST_RESULT_VOID(hrnCmdRestore(), "successful restore");
@@ -2376,7 +2379,8 @@ testRun(void)
// Store archive.info to repo1 - repo1 will be selected because of the priority order
infoArchive = infoArchiveNew(PG_VERSION_11, 6569239123849665679, NULL);
infoArchiveSaveFile(infoArchive, storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeNone, NULL);
infoArchiveSaveFile(
infoArchive, storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNewNone());
hrnCfgArgRawZ(argList, cfgOptTargetTimeline, "0xff");
HRN_CFG_LOAD(cfgCmdRestore, argList);

View File

@@ -133,42 +133,53 @@ testRun(void)
InfoArchive *infoArchive = NULL;
TEST_ASSIGN(
infoArchive,
infoArchiveLoadFile(storageRepoIdx(1), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("12345678")),
infoArchiveLoadFile(
storageRepoIdx(1), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("12345678"))),
"load archive info from encrypted repo2");
TEST_RESULT_PTR_NE(infoArchiveCipherPass(infoArchive), NULL, "cipher sub set");
TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(infoArchive)), cipherTypeAes256Cbc, "cipher sub set");
InfoBackup *infoBackup = NULL;
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("12345678")),
infoBackup,
infoBackupLoadFile(
storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("12345678"))),
"load backup info from encrypted repo2");
TEST_RESULT_PTR_NE(infoBackupCipherPass(infoBackup), NULL, "cipher sub set");
TEST_RESULT_UINT(cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeAes256Cbc, "cipher sub set");
TEST_RESULT_BOOL(
strEq(infoArchiveCipherPass(infoArchive), infoBackupCipherPass(infoBackup)), false,
bufEq(cipherSpecPass(infoArchiveCipherSpec(infoArchive)), cipherSpecPass(infoBackupCipherSpec(infoBackup))), false,
"cipher sub different for archive and backup");
// Confirm non-encrypted repo created successfully
TEST_ASSIGN(
infoArchive, infoArchiveLoadFile(storageRepoIdx(2), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeNone, NULL),
infoArchive,
infoArchiveLoadFile(storageRepoIdx(2), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNewNone()),
"load archive info from repo3");
TEST_RESULT_PTR(infoArchiveCipherPass(infoArchive), NULL, "archive cipher sub not set on non-encrypted repo");
TEST_RESULT_UINT(
cipherSpecType(infoArchiveCipherSpec(infoArchive)), cipherTypeNone,
"archive cipher sub not set on non-encrypted repo");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepoIdx(2), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup, infoBackupLoadFile(storageRepoIdx(2), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"load backup info from repo3");
TEST_RESULT_PTR(infoBackupCipherPass(infoBackup), NULL, "backup cipher sub not set on non-encrypted repo");
TEST_RESULT_UINT(
cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeNone,
"backup cipher sub not set on non-encrypted repo");
// Confirm other repo encrypted with different password
TEST_ASSIGN(
infoArchive,
infoArchiveLoadFile(storageRepoIdx(3), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("87654321")),
infoArchiveLoadFile(
storageRepoIdx(3), INFO_ARCHIVE_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("87654321"))),
"load archive info from encrypted repo4");
TEST_RESULT_PTR_NE(infoArchiveCipherPass(infoArchive), NULL, "cipher sub set");
TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(infoArchive)), cipherTypeAes256Cbc, "cipher sub set");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepoIdx(3), INFO_BACKUP_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("87654321")),
infoBackup,
infoBackupLoadFile(
storageRepoIdx(3), INFO_BACKUP_PATH_FILE_STR, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("87654321"))),
"load backup info from encrypted repo4");
TEST_RESULT_PTR_NE(infoBackupCipherPass(infoBackup), NULL, "cipher sub set");
TEST_RESULT_UINT(cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeAes256Cbc, "cipher sub set");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("cmdStanzaCreate missing files - multi-repo and encryption");

View File

@@ -238,7 +238,8 @@ testRun(void)
InfoPg *infoPg = NULL;
TEST_ASSIGN(
infoPg, infoArchivePg(infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_BASE)))),
infoPg,
infoArchivePg(infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_BASE)), cipherSpecNewNone())),
"infoPg from archive.info");
// -------------------------------------------------------------------------------------------------------------------------
@@ -268,7 +269,8 @@ testRun(void)
harnessLogLevelSet(logLevelDetail);
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_ASSIGN(
manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg version mismatch");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
@@ -303,7 +305,8 @@ testRun(void)
.comment = "manifest copy - invalid system-id");
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_ASSIGN(
manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg system-id mismatch");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
@@ -337,7 +340,8 @@ testRun(void)
.comment = "manifest copy - invalid db-id");
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_ASSIGN(
manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg db-id mismatch");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
@@ -355,7 +359,8 @@ testRun(void)
storageRepoWrite(), TEST_PATH "/repo/" STORAGE_PATH_BACKUP "/db/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE
INFO_COPY_EXT, TEST_INVALID_BACKREST_INFO, .comment = "invalid manifest copy");
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_ASSIGN(
manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
"P00 DETAIL: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152138F/backup.manifest' for read\n"
@@ -369,7 +374,8 @@ testRun(void)
storageRepoWrite(), TEST_PATH "/repo/" STORAGE_PATH_BACKUP "/db/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE,
TEST_INVALID_BACKREST_INFO, .comment = "invalid manifest");
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, true, infoPg, &jobErrorTotal), "verify manifest");
TEST_ASSIGN(
manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), true, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
@@ -395,7 +401,8 @@ testRun(void)
.comment = "valid manifest");
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, true, infoPg, &jobErrorTotal), "verify manifest");
TEST_ASSIGN(
manifest, verifyManifestFile(&backupResult, cipherSpecNewNone(), true, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR_NE(manifest, NULL, "manifest set");
TEST_RESULT_UINT(backupResult.status, backupValid, "manifest usable");
TEST_RESULT_LOG("P00 DETAIL: backup '20181119-152138F' manifest.copy does not match manifest");
@@ -485,7 +492,8 @@ testRun(void)
// Create backup.info
InfoBackup *backupInfo = NULL;
TEST_ASSIGN(
backupInfo, infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE))),
backupInfo,
infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE)), cipherSpecNewNone()),
"backup.info multi-history");
// -------------------------------------------------------------------------------------------------------------------------
@@ -504,7 +512,7 @@ testRun(void)
"db-version=\"11\"\n"
"\n"
"[db:history]\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))),
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()),
"archive.info missing history");
TEST_ERROR(
@@ -526,7 +534,7 @@ testRun(void)
"\n"
"[db:history]\n"
"1={\"db-id\":6625592122879095777,\"db-version\":\"9.6\"}\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))),
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()),
"archive.info history system id mismatch");
TEST_ERROR(
@@ -548,7 +556,7 @@ testRun(void)
"\n"
"[db:history]\n"
"1={\"db-id\":" HRN_PG_SYSTEMID_96_Z ",\"db-version\":\"18\"}\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))),
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()),
"archive.info history version mismatch");
TEST_ERROR(
@@ -570,7 +578,7 @@ testRun(void)
"\n"
"[db:history]\n"
"3={\"db-id\":" HRN_PG_SYSTEMID_96_Z ",\"db-version\":\"10\"}\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))),
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}")), cipherSpecNewNone()),
"archive.info history id mismatch");
TEST_ERROR(
@@ -587,10 +595,12 @@ testRun(void)
InfoBackup *backupInfo = NULL;
InfoArchive *archiveInfo = NULL;
TEST_ASSIGN(
backupInfo, infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE))),
backupInfo,
infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE)), cipherSpecNewNone()),
"backup.info multi-history");
TEST_ASSIGN(
archiveInfo, infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE))),
archiveInfo,
infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE)), cipherSpecNewNone()),
"archive.info multi-history");
InfoPg *pgHistory = infoArchivePg(archiveInfo);
@@ -867,17 +877,17 @@ testRun(void)
HRN_CFG_LOAD(cfgCmdVerify, argList);
HRN_INFO_PUT(
storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_NO_CURRENT_BACKUP, .cipherType = cipherTypeAes256Cbc,
storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_NO_CURRENT_BACKUP, .cipherSpec = TEST_CIPHER_SPEC,
.comment = "encrypted backup.info");
HRN_INFO_PUT(
storageRepoWrite(), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, TEST_NO_CURRENT_BACKUP,
.cipherType = cipherTypeAes256Cbc, .comment = "encrypted backup.info.copy");
.cipherSpec = TEST_CIPHER_SPEC, .comment = "encrypted backup.info.copy");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE,
.cipherType = cipherTypeAes256Cbc, .comment = "encrypted archive.info");
.cipherSpec = TEST_CIPHER_SPEC, .comment = "encrypted archive.info");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE,
.cipherType = cipherTypeAes256Cbc, .comment = "encrypted archive.info.copy");
.cipherSpec = TEST_CIPHER_SPEC, .comment = "encrypted archive.info.copy");
TEST_RESULT_VOID(cmdVerify(), "usable encrypted backup and archive info files");
TEST_RESULT_LOG("");
@@ -899,20 +909,23 @@ testRun(void)
String *filePathName = strNewZ(STORAGE_REPO_ARCHIVE "/testfile");
HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), strZ(filePathName));
TEST_RESULT_UINT(
verifyFile(filePathName, 0, NULL, compressTypeNone, HASH_TYPE_SHA1_ZERO_BUF, 0, NULL), verifyOk, "file ok");
verifyFile(filePathName, 0, NULL, compressTypeNone, HASH_TYPE_SHA1_ZERO_BUF, 0, cipherSpecNewNone()),
verifyOk, "file ok");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("file size invalid in archive");
HRN_STORAGE_PUT_Z(storageRepoWrite(), strZ(filePathName), fileContents);
TEST_RESULT_UINT(
verifyFile(filePathName, 0, NULL, compressTypeNone, fileChecksum, 0, NULL), verifySizeInvalid, "file size invalid");
verifyFile(filePathName, 0, NULL, compressTypeNone, fileChecksum, 0, cipherSpecNewNone()),
verifySizeInvalid, "file size invalid");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("file missing in archive");
TEST_RESULT_UINT(
verifyFile(strNewFmt(STORAGE_REPO_ARCHIVE "/missingFile"), 0, NULL, compressTypeNone, fileChecksum, 0, NULL),
verifyFile(
strNewFmt(STORAGE_REPO_ARCHIVE "/missingFile"), 0, NULL, compressTypeNone, fileChecksum, 0, cipherSpecNewNone()),
verifyFileMissing, "file missing");
// -------------------------------------------------------------------------------------------------------------------------
@@ -921,15 +934,19 @@ testRun(void)
// Create a compressed encrypted repo file in backup
filePathName = strCatZ(strNew(), STORAGE_REPO_BACKUP "/testfile");
HRN_STORAGE_PUT_Z(
storageRepoWrite(), strZ(filePathName), fileContents, .compressType = compressTypeGz, .cipherType = cipherTypeAes256Cbc,
.cipherPass = "pass");
storageRepoWrite(), strZ(filePathName), fileContents, .compressType = compressTypeGz,
.cipherSpec = TEST_CIPHER_SPEC_PASS("pass"));
strCatZ(filePathName, ".gz");
TEST_RESULT_UINT(
verifyFile(filePathName, 0, NULL, compressTypeGz, fileChecksum, fileSize, STRDEF("pass")),
verifyFile(
filePathName, 0, NULL, compressTypeGz, fileChecksum, fileSize,
cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("pass"))),
verifyOk, "file encrypted compressed ok");
TEST_RESULT_UINT(
verifyFile(filePathName, 0, NULL, compressTypeGz, bufNewDecode(encodingHex, STRDEF("aa")), fileSize, STRDEF("pass")),
verifyFile(
filePathName, 0, NULL, compressTypeGz, bufNewDecode(encodingHex, STRDEF("aa")), fileSize,
cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("pass"))),
verifyChecksumMismatch, "file encrypted compressed checksum mismatch");
}
@@ -2497,7 +2514,7 @@ testRun(void)
HRN_CFG_LOAD(cfgCmdBackup, argList);
hrnBackupPqScriptP(
PG_VERSION_11, BACKUP_EPOCH + 200000, .cipherType = cipherTypeAes256Cbc, .cipherPass = TEST_CIPHER_PASS);
PG_VERSION_11, BACKUP_EPOCH + 200000, .cipherSpecMain = TEST_CIPHER_SPEC);
TEST_RESULT_VOID(hrnCmdBackup(), "backup");
TEST_RESULT_LOG(
"P00 INFO: execute backup start: backup begins after the next regular checkpoint completes\n"

View File

@@ -72,18 +72,43 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("CipherBlock"))
{
// Cipher and digest errors
// Cipher error
// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(
cipherBlockNewP(cipherModeEncrypt, cipherTypeNone, BUFSTRZ(TEST_PASS)), AssertError, "unable to load cipher 'none'");
TEST_ERROR(
cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, testPass, .digest = STRDEF(BOGUS_STR)), AssertError,
"unable to load digest 'BOGUS'");
cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(strIdFromZ(BOGUS_STR), testPass)), AssertError,
"unable to load cipher 'BOGUS'");
// Initialization of object
// -------------------------------------------------------------------------------------------------------------------------
CipherBlock *cipherBlock = (CipherBlock *)ioFilterDriver(
cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, BUFSTRZ(TEST_PASS)));
// Build from a duplicate to show the copy carries the type and pass of the original
TEST_RESULT_UINT(cipherSpecType(cipherSpecDup(cipherSpecNewNone())), cipherTypeNone, "dup of none");
const CipherSpec *const cipherSpec = cipherSpecDup(cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF(TEST_PASS)));
TEST_RESULT_UINT(cipherSpecType(cipherSpec), cipherTypeAes256Cbc, "dup type");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(cipherSpec)), TEST_PASS, "dup pass");
// A pack carries nothing but the type when there is no cipher
PackWrite *packWrite = pckWriteNewP();
cipherSpecPack(packWrite, cipherSpecNewNone());
pckWriteEndP(packWrite);
TEST_RESULT_UINT(
cipherSpecType(cipherSpecNewPack(pckReadNew(pckWriteResult(packWrite)))), cipherTypeNone, "unpack none");
// Else it carries the type and pass
packWrite = pckWriteNewP();
cipherSpecPack(packWrite, cipherSpecNew(cipherTypeAes256Cbc, testPass));
pckWriteEndP(packWrite);
const CipherSpec *const cipherSpecUnpack = cipherSpecNewPack(pckReadNew(pckWriteResult(packWrite)));
TEST_RESULT_UINT(cipherSpecType(cipherSpecUnpack), cipherTypeAes256Cbc, "unpack type");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(cipherSpecUnpack)), TEST_PASS, "unpack pass");
CipherBlock *cipherBlock = (CipherBlock *)ioFilterDriver(cipherBlockNewP(cipherModeEncrypt, cipherSpec));
TEST_RESULT_INT(cipherBlock->mode, cipherModeEncrypt, "mode is valid");
TEST_RESULT_UINT(bufSize(cipherBlock->pass), strlen(TEST_PASS), "passphrase size is valid");
TEST_RESULT_BOOL(memcmp(bufPtrConst(cipherBlock->pass), TEST_PASS, strlen(TEST_PASS)) == 0, true, "passphrase is valid");
@@ -98,7 +123,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
Buffer *encryptBuffer = bufNew(TEST_BUFFER_SIZE);
IoFilter *blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, testPass);
IoFilter *blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
blockEncryptFilter = cipherBlockNewPack(ioFilterParamList(blockEncryptFilter));
CipherBlock *blockEncrypt = (CipherBlock *)ioFilterDriver(blockEncryptFilter);
@@ -149,7 +174,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
Buffer *decryptBuffer = bufNew(TEST_BUFFER_SIZE);
IoFilter *blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass, .digest = STRDEF("sha1"));
IoFilter *blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
blockDecryptFilter = cipherBlockNewPack(ioFilterParamList(blockDecryptFilter));
CipherBlock *blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter);
@@ -169,7 +194,7 @@ testRun(void)
// Decrypt in small chunks to test buffering
// -------------------------------------------------------------------------------------------------------------------------
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass);
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter);
bufUsedZero(decryptBuffer);
@@ -210,7 +235,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("encrypt zero byte file with no magic");
blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, testPass, .raw = true);
blockEncryptFilter = cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass), .raw = true);
blockEncrypt = (CipherBlock *)ioFilterDriver(blockEncryptFilter);
bufUsedZero(encryptBuffer);
@@ -223,13 +248,13 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("error on decrypt expecting magic");
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass);
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
TEST_ERROR(ioFilterProcessInOut(blockDecryptFilter, encryptBuffer, decryptBuffer), CryptoError, "cipher header invalid");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("decrypt zero byte file with no magic");
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass, .raw = true);
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass), .raw = true);
blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter);
bufUsedZero(decryptBuffer);
@@ -243,7 +268,7 @@ testRun(void)
// Invalid cipher header
// -------------------------------------------------------------------------------------------------------------------------
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass);
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter);
TEST_ERROR(
@@ -254,7 +279,7 @@ testRun(void)
// Invalid encrypted data cannot be flushed
// -------------------------------------------------------------------------------------------------------------------------
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass);
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter);
bufUsedZero(decryptBuffer);
@@ -268,7 +293,7 @@ testRun(void)
// File with no header should not flush
// -------------------------------------------------------------------------------------------------------------------------
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass);
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter);
bufUsedZero(decryptBuffer);
@@ -279,7 +304,7 @@ testRun(void)
// File with header only should error
// -------------------------------------------------------------------------------------------------------------------------
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, testPass);
blockDecryptFilter = cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, testPass));
blockDecrypt = (CipherBlock *)ioFilterDriver(blockDecryptFilter);
bufUsedZero(decryptBuffer);
@@ -294,11 +319,13 @@ testRun(void)
IoFilterGroup *filterGroup = ioFilterGroupNew();
TEST_RESULT_PTR(
cipherBlockFilterGroupAdd(filterGroup, cipherTypeNone, cipherModeEncrypt, NULL), filterGroup, " no filter add");
cipherBlockFilterGroupAdd(
filterGroup, cipherModeEncrypt, cipherSpecNewNone()), filterGroup, " no filter add");
TEST_RESULT_UINT(ioFilterGroupSize(filterGroup), 0, " check no filter add");
TEST_RESULT_VOID(
cipherBlockFilterGroupAdd(filterGroup, cipherTypeAes256Cbc, cipherModeEncrypt, STRDEF("X")), " filter add");
cipherBlockFilterGroupAdd(
filterGroup, cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("X"))), " filter add");
TEST_RESULT_UINT(ioFilterGroupSize(filterGroup), 1, " check filter add");
}

View File

@@ -936,6 +936,10 @@ testRun(void)
hrnCfgArgRawZ(argList, cfgOptStanza, "db");
hrnCfgArgRawZ(argList, cfgOptPgPath, "/path");
hrnCfgArgRawZ(argList, cfgOptRepoRetentionFull, "1");
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 1, TEST_PATH "/repo1");
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2");
hrnCfgArgKeyRawStrId(argList, cfgOptRepoCipherType, 2, cipherTypeAes256Cbc);
hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 2, "passphrase");
hrnCfgArgRawZ(argList, cfgOptLockPath, HRN_PATH "/lock");
hrnCfgArgRawZ(argList, cfgOptLogPath, TEST_PATH);
hrnCfgArgRawZ(argList, cfgOptLogLevelConsole, "off");
@@ -958,6 +962,16 @@ testRun(void)
TEST_RESULT_INT(socketLocal.tcpKeepAliveInterval, 888, "check socketLocal.tcpKeepAliveInterval");
TEST_RESULT_INT(getpriority(PRIO_PROCESS, (id_t)getpid()), 19, "check priority");
hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 2);
// Cipher spec is cached per repo since each repo has its own cipher type and passphrase
TEST_RESULT_UINT(cipherSpecType(cfgCipherSpecMainIdx(0)), cipherTypeNone, "repo1 cipher spec");
const CipherSpec *const cipherSpecMain = cfgCipherSpecMainIdx(1);
TEST_RESULT_UINT(cipherSpecType(cipherSpecMain), cipherTypeAes256Cbc, "repo2 cipher spec");
TEST_RESULT_PTR(cfgCipherSpecMainIdx(1), cipherSpecMain, "repo2 cipher spec is cached");
cmdLockReleaseP();
// -------------------------------------------------------------------------------------------------------------------------

View File

@@ -1781,6 +1781,8 @@ testRun(void)
hrnCfgArgKeyRawZ(argList, cfgOptRepoS3Bucket, 1, " test ");
hrnCfgArgKeyRawZ(argList, cfgOptRepoS3Endpoint, 1, "test");
hrnCfgArgKeyRawZ(argList, cfgOptRepoS3Region, 1, "test");
hrnCfgArgKeyRawStrId(argList, cfgOptRepoCipherType, 1, cipherTypeAes256Cbc);
hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 1, "xxx-cipher");
strLstAddZ(argList, TEST_COMMAND_BACKUP);
hrnCfgEnvKeyRawZ(cfgOptRepoS3Key, 1, "xxx");
hrnCfgEnvKeyRawZ(cfgOptRepoS3KeySecret, 1, "xxx");
@@ -1820,8 +1822,16 @@ testRun(void)
TEST_RESULT_INT(cfgOptionSource(cfgOptBufferSize), cfgSourceDefault, "buffer-size is source default");
TEST_RESULT_Z(cfgOptionName(cfgOptBufferSize), "buffer-size", "buffer-size name");
// Cipher spec is built once per repo and then cached
const CipherSpec *const cipherSpecMain = cfgCipherSpecMain();
TEST_RESULT_UINT(cipherSpecType(cipherSpecMain), cipherTypeAes256Cbc, "repo1 cipher spec type");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(cipherSpecMain)), "xxx-cipher", "repo1 cipher spec pass");
TEST_RESULT_PTR(cfgCipherSpecMainIdx(0), cipherSpecMain, "repo1 cipher spec is cached");
hrnCfgEnvKeyRemoveRaw(cfgOptRepoS3Key, 1);
hrnCfgEnvKeyRemoveRaw(cfgOptRepoS3KeySecret, 1);
hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 1);
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("global is a valid stanza prefix");
@@ -1841,6 +1851,7 @@ testRun(void)
TEST_RESULT_VOID(cfgParseP(storageTest, strLstSize(argList), strLstPtr(argList), .noResetLogLevel = true), "parse config");
TEST_RESULT_STR_Z(cfgOptionStr(cfgOptPgPath), "/path/to/global/stanza", "default pg-path");
TEST_RESULT_UINT(cipherSpecType(cfgCipherSpecMainIdx(0)), cipherTypeNone, "no cipher spec when repo is not encrypted");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("warnings for environment variables, command-line and config file options");

View File

@@ -38,14 +38,14 @@ testRun(void)
// Load and test move function
MEM_CONTEXT_TEMP_BEGIN()
{
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad)), "load new archive info");
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "load new archive info");
TEST_RESULT_VOID(infoArchiveMove(info, memContextPrior()), "move info");
}
MEM_CONTEXT_TEMP_END();
TEST_RESULT_STR_Z(infoArchiveId(info), "9.6-1", "archiveId set");
TEST_RESULT_PTR(infoArchivePg(info), info->pub.infoPg, "infoPg set");
TEST_RESULT_STR(infoArchiveCipherPass(info), NULL, "no cipher sub");
TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(info)), cipherTypeNone, "no cipher sub");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("infoArchive save (in memory)");
@@ -64,7 +64,7 @@ testRun(void)
info, infoArchiveNew(PG_VERSION_96, 6569239123849665679, NULL), "infoArchiveNew() - no sub cipher");
TEST_RESULT_STR_Z(infoArchiveId(info), "9.6-1", "archiveId set");
TEST_RESULT_PTR(infoArchivePg(info), info->pub.infoPg, "infoPg set");
TEST_RESULT_STR(infoArchiveCipherPass(info), NULL, "no cipher sub");
TEST_RESULT_UINT(cipherSpecType(infoArchiveCipherSpec(info)), cipherTypeNone, "no cipher sub");
TEST_RESULT_INT(infoPgDataTotal(infoArchivePg(info)), 1, "history set");
Buffer *contentCompare = bufNew(0);
@@ -79,18 +79,22 @@ testRun(void)
TEST_ASSIGN(
info,
infoArchiveNew(
PG_VERSION_10, 6569239123849665999, STRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")),
PG_VERSION_10, 6569239123849665999,
cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO"))),
"infoArchiveNew() - cipher sub");
contentSave = bufNew(0);
TEST_RESULT_VOID(infoArchiveSave(info, ioBufferWriteNew(contentSave)), "save new with cipher");
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentSave)), "load encrypted archive info");
TEST_ASSIGN(
info, infoArchiveNewLoad(ioBufferReadNew(contentSave), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))),
"load encrypted archive info");
TEST_RESULT_STR_Z(infoArchiveId(info), "10-1", "archiveId set");
TEST_RESULT_PTR(infoArchivePg(info), infoArchivePg(info), "infoPg set");
TEST_RESULT_STR_Z(
infoArchiveCipherPass(info), "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set");
strNewBuf(cipherSpecPass(infoArchiveCipherSpec(info))),
"zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set");
TEST_RESULT_INT(infoPgDataTotal(infoArchivePg(info)), 1, "history set");
// -------------------------------------------------------------------------------------------------------------------------
@@ -121,7 +125,7 @@ testRun(void)
"1={\"db-id\":6625592122879095702,\"db-version\":\"9.6\"}\n"
"2={\"db-id\":6626363367545678089,\"db-version\":\"17\"}\n");
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad)), "new archive info");
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new archive info");
TEST_RESULT_STR_Z(infoArchiveIdHistoryMatch(info, 2, 170000, 6626363367545678089), "17-2", "full match found");
TEST_RESULT_STR_Z(infoArchiveIdHistoryMatch(info, 2, 90600, 6625592122879095702), "9.6-1", "partial match found");
@@ -142,7 +146,7 @@ testRun(void)
TEST_TITLE("load archive info file - error");
TEST_ERROR(
infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), FileMissingError,
infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()), FileMissingError,
"unable to load info file '" TEST_PATH "/archive.info' or '" TEST_PATH "/archive.info.copy':\n"
"FileMissingError: unable to open missing file '" TEST_PATH "/archive.info' for read\n"
"FileMissingError: unable to open missing file '" TEST_PATH "/archive.info.copy' for read\n"
@@ -156,13 +160,18 @@ testRun(void)
InfoArchive *infoArchive = infoArchiveNew(PG_VERSION_10, 6569239123849665999, NULL);
TEST_RESULT_VOID(
infoArchiveSaveFile(infoArchive, storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "save archive info");
infoArchiveSaveFile(infoArchive, storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()),
"save archive info");
TEST_ASSIGN(infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "load main");
TEST_ASSIGN(
infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()),
"load main");
TEST_RESULT_UINT(infoPgDataCurrent(infoArchivePg(infoArchive)).systemId, 6569239123849665999, "check file loaded");
HRN_STORAGE_REMOVE(storageTest, INFO_ARCHIVE_FILE, .errorOnMissing = true, .comment = "remove main so only copy exists");
TEST_ASSIGN(infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "load copy");
TEST_ASSIGN(
infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherSpecNewNone()),
"load copy");
TEST_RESULT_UINT(infoPgDataCurrent(infoArchivePg(infoArchive)).systemId, 6569239123849665999, "check file loaded");
}
}

View File

@@ -46,7 +46,7 @@ testRun(void)
// Load and test move function then make sure ignore-section is ignored
MEM_CONTEXT_TEMP_BEGIN()
{
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), "new backup info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new backup info");
TEST_RESULT_VOID(infoBackupMove(infoBackup, memContextPrior()), "move info");
}
MEM_CONTEXT_TEMP_END();
@@ -68,9 +68,9 @@ testRun(void)
TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentCompare)), "save backup info from new");
TEST_RESULT_STR(strNewBuf(contentCompare), strNewBuf(contentSave), "check save");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentCompare)), "load backup info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentCompare), cipherSpecNewNone()), "load backup info");
TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackup->pub.infoPg, "infoPg set");
TEST_RESULT_STR(infoBackupCipherPass(infoBackup), NULL, "cipher sub not set");
TEST_RESULT_UINT(cipherSpecType(infoBackupCipherSpec(infoBackup)), cipherTypeNone, "cipher sub not set");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 0, "infoBackupDataTotal returns 0");
// -------------------------------------------------------------------------------------------------------------------------
@@ -80,7 +80,7 @@ testRun(void)
infoBackup,
infoBackupNew(
PG_VERSION_10, 6569239123849665999, hrnPgCatalogVersion(PG_VERSION_10),
STRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")),
cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO"))),
"infoBackupNew() - cipher sub");
contentSave = bufNew(0);
@@ -88,10 +88,13 @@ testRun(void)
TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentSave)), "save new with cipher sub");
infoBackup = NULL;
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentSave)), "load backup info with cipher sub");
TEST_ASSIGN(
infoBackup, infoBackupNewLoad(ioBufferReadNew(contentSave), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))),
"load backup info with cipher sub");
TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackupPg(infoBackup), "infoPg set");
TEST_RESULT_STR_Z(
infoBackupCipherPass(infoBackup), "zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set");
strNewBuf(cipherSpecPass(infoBackupCipherSpec(infoBackup))),
"zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", "cipher sub set");
TEST_RESULT_INT(infoPgDataTotal(infoBackupPg(infoBackup)), 1, "history set");
// -------------------------------------------------------------------------------------------------------------------------
@@ -154,7 +157,7 @@ testRun(void)
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679"
",\"db-version\":\"9.6\"}\n");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), "new backup info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new backup info");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 3, "backup list contains backups");
@@ -312,9 +315,6 @@ testRun(void)
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
"pg_data/postgresql.conf={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"repo-size\":24,\"size\":7,"
@@ -325,7 +325,7 @@ testRun(void)
"pg_data={}\n"
TEST_MANIFEST_PATH_DEFAULT);
TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(manifestContent)), "load manifest");
TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(manifestContent), cipherSpecNewNone()), "load manifest");
TEST_RESULT_VOID(infoBackupDataAdd(infoBackup, manifest), "add a backup");
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 1, "backup added to current");
TEST_ASSIGN(backupData, infoBackupData(infoBackup, 0), "get added backup");
@@ -433,7 +433,9 @@ testRun(void)
"pg_data/base/65536={\"user\":false}\n" \
TEST_MANIFEST_PATH_DEFAULT
TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_MANIFEST_INCR))), "load manifest");
TEST_ASSIGN(
manifest, manifestNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_MANIFEST_INCR)), cipherSpecNewNone()),
"load manifest");
TEST_RESULT_VOID(infoBackupDataAdd(infoBackup, manifest), "add a backup");
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "backup added to current");
TEST_ASSIGN(backupData, infoBackupData(infoBackup, 1), "get added backup");
@@ -568,9 +570,6 @@ testRun(void)
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
"pg_data/postgresql.conf={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"repo-size\":24,\"size\":7,"
@@ -608,9 +607,6 @@ testRun(void)
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
@@ -646,9 +642,6 @@ testRun(void)
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
@@ -684,9 +677,6 @@ testRun(void)
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
@@ -722,7 +712,7 @@ testRun(void)
"upgrade db");
TEST_RESULT_BOOL(infoBackup->pub.updated, true, "info updated");
TEST_RESULT_VOID(
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"save backup info");
TEST_RESULT_BOOL(infoBackup->pub.updated, false, "info not updated");
@@ -731,7 +721,7 @@ testRun(void)
HRN_STORAGE_TIME(storageRepo(), INFO_BACKUP_PATH_FILE, timeBeforeSave);
TEST_RESULT_VOID(
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"save backup again");
// Check that timestamp was not updated
@@ -741,13 +731,14 @@ testRun(void)
// Reload infoBackup to be sure it was updated
infoBackup = NULL;
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"get saved backup info");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 2, "backup list contains backups to be removed");
TEST_RESULT_INT(infoPgDataTotal(infoBackupPg(infoBackup)), 2, "multiple DB history");
TEST_ASSIGN(
infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup,
infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"reconstruct");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 1, "backup list contains 1 backup");
TEST_ASSIGN(backupData, infoBackupData(infoBackup, 0), "get the backup");
@@ -769,7 +760,8 @@ testRun(void)
storageRepoWrite(), STORAGE_REPO_BACKUP "/20190818-084502F_20190820-084502I", .recurse = true,
.comment = "remove dependent backup from disk");
TEST_ASSIGN(
infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup,
infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"reconstruct does not attempt to add back dependent backup");
TEST_RESULT_LOG(
"P00 WARN: backup '20190818-084502F_20190820-084502I' missing manifest removed from backup.info\n"
@@ -869,12 +861,13 @@ testRun(void)
.comment = "write manifest for backup in a set that is in backup.info but whose prior backup is not");
TEST_RESULT_VOID(
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"save updated backup info");
infoBackup = NULL;
TEST_ASSIGN(
infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
infoBackup,
infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherSpecNewNone()),
"reconstruct");
TEST_RESULT_STRLST_Z(
infoBackupDataLabelList(infoBackup, NULL),
@@ -896,7 +889,7 @@ testRun(void)
TEST_TITLE("load backup info file - error");
TEST_ERROR(
infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), FileMissingError,
infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()), FileMissingError,
"unable to load info file '" TEST_PATH "/backup.info' or '" TEST_PATH "/backup.info.copy':\n"
"FileMissingError: unable to open missing file '" TEST_PATH "/backup.info' for read\n"
"FileMissingError: unable to open missing file '" TEST_PATH "/backup.info.copy' for read\n"
@@ -908,13 +901,18 @@ testRun(void)
InfoBackup *infoBackup = infoBackupNew(PG_VERSION_10, 6569239123849665999, hrnPgCatalogVersion(PG_VERSION_10), NULL);
TEST_RESULT_VOID(
infoBackupSaveFile(infoBackup, storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "save backup info");
infoBackupSaveFile(
infoBackup, storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()), "save backup info");
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "load main");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()),
"load main");
TEST_RESULT_UINT(infoPgDataCurrent(infoBackupPg(infoBackup)).systemId, 6569239123849665999, "check file loaded");
HRN_STORAGE_REMOVE(storageTest, INFO_BACKUP_FILE, .errorOnMissing = true, .comment = "remove main so only copy exists");
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "load copy");
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherSpecNewNone()),
"load copy");
TEST_RESULT_UINT(infoPgDataCurrent(infoBackupPg(infoBackup)).systemId, 6569239123849665999, "check file loaded");
}
@@ -998,7 +996,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("check dependency lists");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), "new backup info");
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone()), "new backup info");
TEST_ASSIGN(dependencyList, infoBackupDataDependentList(infoBackup, STRDEF("20200317-181625F")), "full");
TEST_RESULT_STRLST_Z(

View File

@@ -38,12 +38,14 @@ testRun(void)
TEST_ASSIGN(infoPg, infoPgNew(infoPgBackup, NULL), "infoPgNew(cipherTypeNone, NULL)");
TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history");
TEST_RESULT_STR(infoCipherPass(infoPgInfo(infoPg)), NULL, " cipherPass NULL");
TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(infoPgInfo(infoPg))), cipherTypeNone, " cipher spec none");
TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent");
TEST_ASSIGN(infoPg, infoPgNew(infoPgArchive, STRDEF("123xyz")), "infoPgNew(cipherTypeAes256Cbc, 123xyz)");
TEST_ASSIGN(
infoPg, infoPgNew(infoPgArchive, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("123xyz"))),
"infoPgNew(cipherTypeAes256Cbc, 123xyz)");
TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history");
TEST_RESULT_STR_Z(infoCipherPass(infoPgInfo(infoPg)), "123xyz", " cipherPass set");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(infoPgInfo(infoPg)))), "123xyz", " cipherPass set");
TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent");
// -------------------------------------------------------------------------------------------------------------------------
@@ -71,13 +73,14 @@ testRun(void)
TEST_RESULT_UINT(pgData.systemId, 6569239123849665999, " system-id updated");
TEST_RESULT_UINT(pgData.version, PG_VERSION_18, " version updated");
TEST_RESULT_UINT(pgData.catalogVersion, 0, " catalog version not set for archive");
TEST_RESULT_STR(infoCipherPass(infoPgInfo(infoPg)), NULL, " cipherPass not set");
TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(infoPgInfo(infoPg))), cipherTypeNone, " cipher spec none");
// -------------------------------------------------------------------------------------------------------------------------
TEST_ASSIGN(
infoPg,
infoPgSet(
infoPgNew(infoPgBackup, STRDEF("123xyz")), infoPgBackup, PG_VERSION_18, 6569239123849665679,
infoPgNew(infoPgBackup, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("123xyz"))), infoPgBackup,
PG_VERSION_18, 6569239123849665679,
hrnPgCatalogVersion(PG_VERSION_18)),
"infoPgSet - infoPgBackup");
TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history");
@@ -87,7 +90,7 @@ testRun(void)
TEST_RESULT_UINT(pgData.systemId, 6569239123849665679, " system-id set");
TEST_RESULT_UINT(pgData.version, PG_VERSION_18, " version set");
TEST_RESULT_UINT(pgData.catalogVersion, 202506291, " catalog version updated");
TEST_RESULT_STR_Z(infoCipherPass(infoPgInfo(infoPg)), "123xyz", " cipherPass set");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(infoPgInfo(infoPg)))), "123xyz", " cipherPass set");
}
// *****************************************************************************************************************************
@@ -117,7 +120,9 @@ testRun(void)
InfoPg *infoPg = NULL;
TEST_ASSIGN(
infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgArchive, harnessInfoLoadNewCallback, callbackContent),
infoPg,
infoPgNewLoad(
ioBufferReadNew(contentLoad), infoPgArchive, cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent),
"load file");
TEST_RESULT_STR_Z(
callbackContent,
@@ -133,7 +138,7 @@ testRun(void)
TEST_RESULT_UINT(pgData.systemId, 6569239123849665679, " system-id set");
TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " check pg data total");
TEST_RESULT_STR_Z(infoPgArchiveId(infoPg, 0), "18-1", " check pg archive id");
TEST_RESULT_STR(infoPgCipherPass(infoPg), NULL, " no cipher passphrase");
TEST_RESULT_UINT(cipherSpecType(infoPgCipherSpec(infoPg)), cipherTypeNone, " no cipher passphrase");
Buffer *contentSave = bufNew(0);
@@ -167,7 +172,8 @@ testRun(void)
callbackContent = strNew();
TEST_ASSIGN(infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgBackup, NULL, NULL), "load file");
TEST_ASSIGN(
infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgBackup, cipherSpecNewNone(), NULL, NULL), "load file");
TEST_RESULT_STR_Z(callbackContent, "", " check callback content");
TEST_RESULT_INT(infoPgDataTotal(infoPg), 2, " check pg data total");

View File

@@ -78,11 +78,11 @@ testRun(void)
{
Info *info = NULL;
TEST_ASSIGN(info, infoNew(STRDEF("123xyz")), "infoNew(cipher)");
TEST_RESULT_STR_Z(infoCipherPass(info), "123xyz", " cipherPass is set");
TEST_ASSIGN(info, infoNew(cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("123xyz"))), "infoNew(cipher)");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(info))), "123xyz", " cipherPass is set");
TEST_ASSIGN(info, infoNew(NULL), "infoNew(NULL)");
TEST_RESULT_STR(infoCipherPass(info), NULL, " cipherPass is NULL");
TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(info)), cipherTypeNone, " cipher spec is none");
}
// *****************************************************************************************************************************
@@ -97,8 +97,8 @@ testRun(void)
String *callbackContent = strNew();
TEST_ERROR(
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), FormatError,
"expected format 5 but found 4");
infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent),
FormatError, "expected format 5 but found 4");
TEST_RESULT_STR_Z(callbackContent, "", " check callback content");
// Checksum not found
@@ -108,8 +108,8 @@ testRun(void)
"backrest-format=5\n");
TEST_ERROR(
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), ChecksumError,
"invalid checksum, actual 'a3765a8c2c1e5d35274a0b0ce118f4031faff0bd' but no checksum found");
infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent),
ChecksumError, "invalid checksum, actual 'a3765a8c2c1e5d35274a0b0ce118f4031faff0bd' but no checksum found");
TEST_RESULT_STR_Z(callbackContent, "", " check callback content");
// Checksum invalid
@@ -122,8 +122,8 @@ testRun(void)
"bogus=\"BOGUS\"\n");
TEST_ERROR(
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), ChecksumError,
"invalid checksum, actual 'fe989a75dcf7a0261e57d210707c0db741462763' but expected 'BOGUS'");
infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent),
ChecksumError, "invalid checksum, actual 'fe989a75dcf7a0261e57d210707c0db741462763' but expected 'BOGUS'");
TEST_RESULT_STR_Z(callbackContent, "", " check callback content");
// Crypto expected
@@ -135,10 +135,12 @@ testRun(void)
"backrest-version=\"2.17\"\n");
IoRead *read = ioBufferReadNew(contentLoad);
ioFilterGroupAdd(ioReadFilterGroup(read), cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTRDEF("X")));
ioFilterGroupAdd(
ioReadFilterGroup(read),
cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("X"))));
TEST_ERROR(
infoNewLoad(read, harnessInfoLoadNewCallback, callbackContent), CryptoError,
infoNewLoad(read, cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent), CryptoError,
"cipher header invalid\n"
"HINT: is or was the repo encrypted?");
TEST_RESULT_STR_Z(callbackContent, "", " check callback content");
@@ -153,9 +155,10 @@ testRun(void)
callbackContent = strNew();
TEST_ASSIGN(
info, infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with other cipher");
info, infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent),
"info with other cipher");
TEST_RESULT_STR_Z(callbackContent, "", " check callback content");
TEST_RESULT_STR(infoCipherPass(info), NULL, " check cipher pass not set");
TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(info)), cipherTypeNone, " check cipher pass not set");
// Base file with content
// -------------------------------------------------------------------------------------------------------------------------
@@ -169,9 +172,10 @@ testRun(void)
callbackContent = strNew();
TEST_ASSIGN(
info, infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with content");
info, infoNewLoad(ioBufferReadNew(contentLoad), cipherSpecNewNone(), harnessInfoLoadNewCallback, callbackContent),
"info with content");
TEST_RESULT_STR_Z(callbackContent, "[c] key=1\n[d] key=1\n", " check callback content");
TEST_RESULT_STR(infoCipherPass(info), NULL, " check cipher pass not set");
TEST_RESULT_UINT(cipherSpecType(infoCipherSpec(info)), cipherTypeNone, " check cipher pass not set");
Buffer *contentSave = bufNew(0);
@@ -194,9 +198,12 @@ testRun(void)
TEST_ASSIGN(
info,
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with content and cipher");
infoNewLoad(
ioBufferReadNew(contentLoad), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x")), harnessInfoLoadNewCallback,
callbackContent),
"info with content and cipher");
TEST_RESULT_STR_Z(callbackContent, "[c] key=1\n[d] key=1\n", " check callback content");
TEST_RESULT_STR_Z(infoCipherPass(info), "somepass", " check cipher pass set");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(infoCipherSpec(info))), "somepass", " check cipher pass set");
TEST_RESULT_STR_Z(infoBackrestVersion(info), PROJECT_VERSION, " check backrest version");
contentSave = bufNew(0);

View File

@@ -1469,7 +1469,9 @@ testRun(void)
MEM_CONTEXT_TEMP_BEGIN()
{
TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(contentLoad)), "load manifest");
TEST_ASSIGN(
manifest, manifestNewLoad(ioBufferReadNew(contentLoad), cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))),
"load manifest");
TEST_RESULT_VOID(manifestMove(manifest, memContextPrior()), "move manifest");
}
MEM_CONTEXT_TEMP_END();
@@ -1481,7 +1483,7 @@ testRun(void)
manifestTargetFind(manifest, STRDEF("bogus")), AssertError, "unable to find 'bogus' in manifest target list");
TEST_RESULT_STR_Z(manifestData(manifest)->backupLabel, "20190808-163540F", "check manifest data");
TEST_RESULT_STR_Z(manifestCipherSubPass(manifest), "somepass", "check cipher subpass");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(manifestCipherSpec(manifest))), "somepass", "check cipher subpass");
TEST_RESULT_VOID(
manifestTargetUpdate(manifest, MANIFEST_TARGET_PGDATA_STR, STRDEF("/pg/base"), NULL), "update target no change");
@@ -1671,7 +1673,7 @@ testRun(void)
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT))),
TEST_MANIFEST_PATH_DEFAULT)), cipherSpecNewNone()),
"load manifest");
// -------------------------------------------------------------------------------------------------------------------------
@@ -1768,9 +1770,11 @@ testRun(void)
TEST_RESULT_STR_Z(manifestPathPg(STRDEF("pg_data/PG_VERSION")), "PG_VERSION", "check pg_data path/file");
TEST_RESULT_STR_Z(manifestPathPg(STRDEF("pg_tblspc/1")), "pg_tblspc/1", "check pg_tblspc path/file");
TEST_RESULT_STR_Z(manifestCipherSubPass(manifest), NULL, "check cipher subpass");
TEST_RESULT_VOID(manifestCipherSubPassSet(manifest, STRDEF("supersecret")), "cipher subpass set");
TEST_RESULT_STR_Z(manifestCipherSubPass(manifest), "supersecret", "check cipher subpass");
TEST_RESULT_UINT(cipherSpecType(manifestCipherSpec(manifest)), cipherTypeNone, "check cipher subpass");
TEST_RESULT_VOID(
manifestCipherSpecSet(manifest, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("supersecret"))),
"cipher subpass set");
TEST_RESULT_STR_Z(strNewBuf(cipherSpecPass(manifestCipherSpec(manifest))), "supersecret", "check cipher subpass");
// Absolute target paths
TEST_RESULT_STR_Z(manifestTargetPath(manifest, manifestTargetBase(manifest)), "/pg/base", "base target path");
@@ -1957,11 +1961,11 @@ testRun(void)
TEST_TITLE("load validation errors");
TEST_ERROR(
manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"size\":0}"))), FormatError,
"missing timestamp for file 'pg_data/bogus'");
manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"size\":0}")), cipherSpecNewNone()),
FormatError, "missing timestamp for file 'pg_data/bogus'");
TEST_ERROR(
manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"timestamp\":0}"))), FormatError,
"missing size for file 'pg_data/bogus'");
manifestNewLoad(ioBufferReadNew(BUFSTRDEF("[target:file]\npg_data/bogus={\"timestamp\":0}")), cipherSpecNewNone()),
FormatError, "missing size for file 'pg_data/bogus'");
}
// *****************************************************************************************************************************
@@ -1970,7 +1974,7 @@ testRun(void)
Manifest *manifest = NULL;
TEST_ERROR(
manifestLoadFile(storageTest, BACKUP_MANIFEST_FILE_STR, cipherTypeNone, NULL), FileMissingError,
manifestLoadFile(storageTest, BACKUP_MANIFEST_FILE_STR, cipherSpecNewNone()), FileMissingError,
"unable to load backup manifest file '" TEST_PATH "/backup.manifest' or '" TEST_PATH "/backup.manifest.copy':\n"
"FileMissingError: unable to open missing file '" TEST_PATH "/backup.manifest' for read\n"
"FileMissingError: unable to open missing file '" TEST_PATH "/backup.manifest.copy' for read");
@@ -2034,14 +2038,18 @@ testRun(void)
"user=\"user1\"\n"
HRN_INFO_PUT(storageTest, BACKUP_MANIFEST_FILE INFO_COPY_EXT, TEST_MANIFEST_CONTENT, .comment = "write manifest copy");
TEST_ASSIGN(manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherTypeNone, NULL), "load copy");
TEST_ASSIGN(
manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherSpecNewNone()),
"load copy");
TEST_RESULT_UINT(manifestData(manifest)->pgSystemId, 1000000000000000094, "check file loaded");
TEST_RESULT_STR_Z(manifestData(manifest)->backrestVersion, PROJECT_VERSION, "check backrest version");
HRN_STORAGE_REMOVE(storageTest, BACKUP_MANIFEST_FILE INFO_COPY_EXT, .errorOnMissing = true);
HRN_INFO_PUT(storageTest, BACKUP_MANIFEST_FILE, TEST_MANIFEST_CONTENT, .comment = "write main manifest");
TEST_ASSIGN(manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherTypeNone, NULL), "load main");
TEST_ASSIGN(
manifest, manifestLoadFile(storageTest, STRDEF(BACKUP_MANIFEST_FILE), cipherSpecNewNone()),
"load main");
TEST_RESULT_UINT(manifestData(manifest)->pgSystemId, 1000000000000000094, "check file loaded");
TEST_RESULT_VOID(manifestFree(manifest), "free manifest");

View File

@@ -200,14 +200,14 @@ testRun(void)
{
// Check backups before the backup so we know how many will exist after
const InfoBackup *infoBackup = infoBackupLoadFile(
hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherType(), hrnHostCipherPass());
hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherSpec());
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 1, "backup total = 1");
TEST_HOST_BR(repo, CFGCMD_BACKUP, .option = "--type=full --backup-standby --repo1-retention-full=1 --no-expire-auto");
// Expire was disabled so the backup total has increased
infoBackup = infoBackupLoadFile(
hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherType(), hrnHostCipherPass());
hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherSpec());
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "backup total = 2");
// Now force an expire
@@ -215,7 +215,7 @@ testRun(void)
// Backup has been expired
infoBackup = infoBackupLoadFile(
hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherType(), hrnHostCipherPass());
hrnHostRepo1Storage(repo), STRDEF("backup/" HRN_STANZA "/backup.info"), hrnHostCipherSpec());
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 1, "backup total = 1");
// Stop the standby since restores to primary will break it

View File

@@ -302,7 +302,7 @@ testRun(void)
MEM_CONTEXT_BEGIN(testContext)
{
manifest = manifestNewLoad(ioBufferReadNew(contentSave));
manifest = manifestNewLoad(ioBufferReadNew(contentSave), cipherSpecNewNone());
}
MEM_CONTEXT_END();

View File

@@ -381,8 +381,8 @@ testRun(void)
IoFilterGroup *filterGroup = ioReadFilterGroup(storageReadIo(fileRead));
ioFilterGroupAdd(filterGroup, ioSizeNew());
ioFilterGroupAdd(filterGroup, cryptoHashNew(hashTypeSha1));
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, cipherTypeAes256Cbc, BUFSTRZ("x")));
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTRZ("x")));
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeEncrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))));
ioFilterGroupAdd(filterGroup, cipherBlockNewP(cipherModeDecrypt, cipherSpecNew(cipherTypeAes256Cbc, BUFSTRDEF("x"))));
ioFilterGroupAdd(filterGroup, compressFilterP(compressTypeGz, 3));
ioFilterGroupAdd(filterGroup, decompressFilterP(compressTypeGz));