You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-11-06 08:49:29 +02:00
Add strNewEncode(), strCatEncode(), and bufNewDecode().
These constructors wrap encodeToStr() and decodeToBin(), making them convenient and safe by eliminating the need to create intermediate buffers. Encoding/decoding is performed directly into the target String/Buffer. Sizing of the destination buffer is handled by the new functions so it doesn't have to be done at each call site.
This commit is contained in:
@@ -5,7 +5,6 @@ Stanza Commands Handler
|
||||
|
||||
#include "command/check/common.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/encode.h"
|
||||
#include "common/log.h"
|
||||
#include "config/config.h"
|
||||
#include "db/helper.h"
|
||||
@@ -27,12 +26,9 @@ cipherPassGen(CipherType cipherType)
|
||||
if (cipherType != cipherTypeNone)
|
||||
{
|
||||
unsigned char buffer[48]; // 48 is the amount of entropy needed to get a 64 base key
|
||||
char cipherPassSubChar[65];
|
||||
ASSERT(encodeToStrSize(encodeBase64, sizeof(buffer)) + 1 == sizeof(cipherPassSubChar));
|
||||
|
||||
cryptoRandomBytes(buffer, sizeof(buffer));
|
||||
encodeToStr(encodeBase64, buffer, sizeof(buffer), cipherPassSubChar);
|
||||
result = strNew(cipherPassSubChar);
|
||||
|
||||
result = strNewEncode(encodeBase64, BUF(buffer, sizeof(buffer)));
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
|
||||
@@ -6,6 +6,8 @@ These high-level functions are preferred to the low-level functions for each enc
|
||||
#ifndef COMMON_ENCODE_H
|
||||
#define COMMON_ENCODE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Encoding types
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
@@ -87,6 +87,23 @@ bufNewC(const void *buffer, size_t size)
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
Buffer *
|
||||
bufNewDecode(EncodeType type, const String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, type);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
Buffer *this = bufNew(decodeToBinSize(type, strZ(string)));
|
||||
|
||||
decodeToBin(type, strZ(string), bufPtr(this));
|
||||
bufUsedSet(this, bufSize(this));
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
Buffer *
|
||||
bufDup(const Buffer *buffer)
|
||||
|
||||
@@ -43,6 +43,10 @@ Buffer *bufNew(size_t size);
|
||||
// Create a new buffer from a C buffer
|
||||
Buffer *bufNewC(const void *buffer, size_t size);
|
||||
|
||||
// Create a new buffer from a string encoded with the specified type
|
||||
Buffer *bufNewDecode(EncodeType type, const String *string);
|
||||
|
||||
// Duplicate a buffer
|
||||
Buffer *bufDup(const Buffer *buffer);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
|
||||
@@ -138,6 +138,37 @@ strNewBuf(const Buffer *buffer)
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strNewEncode(EncodeType type, const Buffer *buffer)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, type);
|
||||
FUNCTION_TEST_PARAM(BUFFER, buffer);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(buffer != NULL);
|
||||
|
||||
// Check encoded size
|
||||
size_t size = encodeToStrSize(type, bufUsed(buffer));
|
||||
CHECK_SIZE(size);
|
||||
|
||||
// Create object
|
||||
String *this = memNew(sizeof(String));
|
||||
|
||||
*this = (String)
|
||||
{
|
||||
.memContext = memContextCurrent(),
|
||||
.size = (unsigned int)size,
|
||||
};
|
||||
|
||||
// Allocate and encode buffer
|
||||
this->buffer = memNew(this->size + 1);
|
||||
encodeToStr(type, bufPtrConst(buffer), bufUsed(buffer), this->buffer);
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strNewFmt(const char *format, ...)
|
||||
@@ -394,6 +425,33 @@ strCatChr(String *this, char cat)
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strCatEncode(String *this, EncodeType type, const Buffer *buffer)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, this);
|
||||
FUNCTION_TEST_PARAM(ENUM, type);
|
||||
FUNCTION_TEST_PARAM(BUFFER, buffer);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(buffer != NULL);
|
||||
|
||||
// Ensure there is enough space to grow the string
|
||||
size_t encodeSize = encodeToStrSize(type, bufUsed(buffer));
|
||||
strResize(this, encodeSize);
|
||||
|
||||
// Append the encoded string
|
||||
encodeToStr(type, bufPtrConst(buffer), bufUsed(buffer), this->buffer + this->size);
|
||||
|
||||
// Update size/extra
|
||||
this->size += (unsigned int)encodeSize;
|
||||
this->extra -= (unsigned int)encodeSize;
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strCatFmt(String *this, const char *format, ...)
|
||||
|
||||
@@ -36,6 +36,7 @@ String object
|
||||
typedef struct String String;
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/encode.h"
|
||||
#include "common/type/buffer.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@@ -67,6 +68,9 @@ String *strNewBuf(const Buffer *buffer);
|
||||
// Create a new string by converting the double value
|
||||
String *strNewDbl(double value);
|
||||
|
||||
// Create a new string encoded with the specified type (e.g. encodeBase64) from a buffer
|
||||
String *strNewEncode(EncodeType type, const Buffer *buffer);
|
||||
|
||||
// Create a new string from a format string with parameters (i.e. sprintf)
|
||||
String *strNewFmt(const char *format, ...) __attribute__((format(printf, 1, 2)));
|
||||
|
||||
@@ -96,6 +100,9 @@ String *strCatZ(String *this, const char *cat);
|
||||
// Append a character
|
||||
String *strCatChr(String *this, char cat);
|
||||
|
||||
// Append a string encoded with the specified type (e.g. encodeBase64) from a buffer
|
||||
String *strCatEncode(String *this, EncodeType type, const Buffer *buffer);
|
||||
|
||||
// Append a formatted string
|
||||
String *strCatFmt(String *this, const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ Info Handler
|
||||
#include "common/type/convert.h"
|
||||
#include "common/crypto/hash.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/encode.h"
|
||||
#include "common/io/filter/filter.intern.h"
|
||||
#include "common/ini.h"
|
||||
#include "common/log.h"
|
||||
|
||||
@@ -7,7 +7,6 @@ Azure Storage
|
||||
|
||||
#include "common/crypto/common.h"
|
||||
#include "common/crypto/hash.h"
|
||||
#include "common/encode.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/io/http/client.h"
|
||||
#include "common/io/http/common.h"
|
||||
@@ -71,7 +70,7 @@ struct StorageAzure
|
||||
|
||||
const String *container; // Container to store data in
|
||||
const String *account; // Account
|
||||
const String *sharedKey; // Shared key
|
||||
const Buffer *sharedKey; // Shared key
|
||||
const HttpQuery *sasKey; // SAS key
|
||||
const String *host; // Host name
|
||||
size_t blockSize; // Block size for multi-block upload
|
||||
@@ -171,17 +170,9 @@ storageAzureAuth(
|
||||
strZ(dateTime), strZ(headerCanonical), strZ(this->account), strZ(path), strZ(queryCanonical));
|
||||
|
||||
// Generate authorization header
|
||||
Buffer *keyBin = bufNew(decodeToBinSize(encodeBase64, strZ(this->sharedKey)));
|
||||
decodeToBin(encodeBase64, strZ(this->sharedKey), bufPtr(keyBin));
|
||||
bufUsedSet(keyBin, bufSize(keyBin));
|
||||
|
||||
char authHmacBase64[45];
|
||||
encodeToStr(
|
||||
encodeBase64, bufPtr(cryptoHmacOne(HASH_TYPE_SHA256_STR, keyBin, BUFSTR(stringToSign))),
|
||||
HASH_TYPE_SHA256_SIZE, authHmacBase64);
|
||||
|
||||
httpHeaderPut(
|
||||
httpHeader, HTTP_HEADER_AUTHORIZATION_STR, strNewFmt("SharedKey %s:%s", strZ(this->account), authHmacBase64));
|
||||
httpHeader, HTTP_HEADER_AUTHORIZATION_STR, strNewFmt("SharedKey %s:%s", strZ(this->account),
|
||||
strZ(strNewEncode(encodeBase64, cryptoHmacOne(HASH_TYPE_SHA256_STR, this->sharedKey, BUFSTR(stringToSign))))));
|
||||
}
|
||||
// SAS authentication
|
||||
else
|
||||
@@ -229,9 +220,9 @@ storageAzureRequestAsync(StorageAzure *this, const String *verb, StorageAzureReq
|
||||
// Calculate content-md5 header if there is content
|
||||
if (param.content != NULL)
|
||||
{
|
||||
char md5Hash[HASH_TYPE_MD5_SIZE_HEX];
|
||||
encodeToStr(encodeBase64, bufPtr(cryptoHashOne(HASH_TYPE_MD5_STR, param.content)), HASH_TYPE_M5_SIZE, md5Hash);
|
||||
httpHeaderAdd(requestHeader, HTTP_HEADER_CONTENT_MD5_STR, STR(md5Hash));
|
||||
httpHeaderAdd(
|
||||
requestHeader, HTTP_HEADER_CONTENT_MD5_STR,
|
||||
strNewEncode(encodeBase64, cryptoHashOne(HASH_TYPE_MD5_STR, param.content)));
|
||||
}
|
||||
|
||||
// Encode path
|
||||
@@ -773,7 +764,7 @@ storageAzureNew(
|
||||
|
||||
// Store shared key or parse sas query
|
||||
if (keyType == storageAzureKeyTypeShared)
|
||||
driver->sharedKey = key;
|
||||
driver->sharedKey = bufNewDecode(encodeBase64, key);
|
||||
else
|
||||
driver->sasKey = httpQueryNewStr(key);
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ Azure Storage File Write
|
||||
#include <string.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/encode.h"
|
||||
#include "common/io/write.intern.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
|
||||
@@ -6,7 +6,6 @@ S3 Storage
|
||||
#include <string.h>
|
||||
|
||||
#include "common/crypto/hash.h"
|
||||
#include "common/encode.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/io/http/client.h"
|
||||
#include "common/io/http/common.h"
|
||||
@@ -306,9 +305,9 @@ storageS3RequestAsync(StorageS3 *this, const String *verb, const String *path, S
|
||||
// Calculate content-md5 header if there is content
|
||||
if (param.content != NULL)
|
||||
{
|
||||
char md5Hash[HASH_TYPE_MD5_SIZE_HEX];
|
||||
encodeToStr(encodeBase64, bufPtr(cryptoHashOne(HASH_TYPE_MD5_STR, param.content)), HASH_TYPE_M5_SIZE, md5Hash);
|
||||
httpHeaderAdd(requestHeader, HTTP_HEADER_CONTENT_MD5_STR, STR(md5Hash));
|
||||
httpHeaderAdd(
|
||||
requestHeader, HTTP_HEADER_CONTENT_MD5_STR,
|
||||
strNewEncode(encodeBase64, cryptoHashOne(HASH_TYPE_MD5_STR, param.content)));
|
||||
}
|
||||
|
||||
// When using path-style URIs the bucket name needs to be prepended
|
||||
|
||||
@@ -113,6 +113,14 @@ unit:
|
||||
coverage:
|
||||
- common/time
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: encode
|
||||
total: 1
|
||||
|
||||
coverage:
|
||||
- common/encode
|
||||
- common/encode/base64
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-string
|
||||
total: 26
|
||||
@@ -315,14 +323,6 @@ unit:
|
||||
coverage:
|
||||
- common/exec
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: encode
|
||||
total: 1
|
||||
|
||||
coverage:
|
||||
- common/encode
|
||||
- common/encode/base64
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: ini
|
||||
total: 4
|
||||
|
||||
@@ -11,7 +11,7 @@ testRun(void)
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("bufNew(), bufNewC, bufNewUseC, bufMove(), bufSize(), bufSizeAlloc(), bufPtr(), and bufFree()"))
|
||||
if (testBegin("bufNew*(), bufMove(), bufSize(), bufSizeAlloc(), bufPtr(), and bufFree()"))
|
||||
{
|
||||
Buffer *buffer = NULL;
|
||||
|
||||
@@ -39,6 +39,11 @@ testRun(void)
|
||||
|
||||
TEST_ASSIGN(buffer, bufNewC(cBuffer, sizeof(cBuffer)), "create from c buffer");
|
||||
TEST_RESULT_BOOL(memcmp(bufPtr(buffer), cBuffer, sizeof(cBuffer)) == 0, true, "check buffer");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("bufNewDecode()");
|
||||
|
||||
TEST_RESULT_STR_Z(strNewBuf(bufNewDecode(encodeBase64, STRDEF("eno="))), "zz", "decode base64");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
|
||||
@@ -15,7 +15,7 @@ testRun(void)
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("strNew(), strNewBuf(), strNewDbl(), strNewN(), strEmpty(), strZ(), strZNull(), strSize(), and strFree()"))
|
||||
if (testBegin("strNew*(), strEmpty(), strZ(), strZNull(), strSize(), and strFree()"))
|
||||
{
|
||||
// We don't want this struct to grow since there are generally a lot of strings, so make sure it doesn't grow without us
|
||||
// knowing about it
|
||||
@@ -63,6 +63,11 @@ testRun(void)
|
||||
TEST_ASSIGN(string, strNew(""), "new empty string");
|
||||
TEST_RESULT_UINT(string->size, 0, " check size");
|
||||
TEST_RESULT_UINT(string->extra, 64, " check extra");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("strNewEncode()");
|
||||
|
||||
TEST_RESULT_STR_Z(strNewEncode(encodeBase64, BUFSTRDEF("zz")), "eno=", "encode base64");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
@@ -99,7 +104,7 @@ testRun(void)
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("strCat(), strCatChr(), and strCatFmt()"))
|
||||
if (testBegin("strCat*()"))
|
||||
{
|
||||
String *string = strNew("XXXX");
|
||||
String *string2 = strNew("ZZZZ");
|
||||
@@ -114,6 +119,10 @@ testRun(void)
|
||||
strCatZN(string, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*", 55),
|
||||
"XXXXYYYY00777!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", "cat chr");
|
||||
TEST_RESULT_UINT(string->extra, 34, "check extra");
|
||||
TEST_RESULT_STR_Z(
|
||||
strCatEncode(string, encodeBase64, BUFSTRDEF("zzzzz")),
|
||||
"XXXXYYYY00777!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$enp6eno=", "cat encode");
|
||||
TEST_RESULT_UINT(string->extra, 26, "check extra");
|
||||
|
||||
TEST_RESULT_STR_Z(string2, "ZZZZ", "check unaltered string");
|
||||
}
|
||||
|
||||
@@ -73,9 +73,9 @@ testRequest(IoWrite *write, const char *verb, const char *path, TestRequestParam
|
||||
// Add md5
|
||||
if (param.content != NULL)
|
||||
{
|
||||
char md5Hash[HASH_TYPE_MD5_SIZE_HEX];
|
||||
encodeToStr(encodeBase64, bufPtr(cryptoHashOne(HASH_TYPE_MD5_STR, BUFSTRZ(param.content))), HASH_TYPE_M5_SIZE, md5Hash);
|
||||
strCatFmt(request, "content-md5:%s\r\n", md5Hash);
|
||||
strCatFmt(
|
||||
request, "content-md5:%s\r\n",
|
||||
strZ(strNewEncode(encodeBase64, cryptoHashOne(HASH_TYPE_MD5_STR, BUFSTRZ(param.content)))));
|
||||
}
|
||||
|
||||
// Add date
|
||||
@@ -190,7 +190,8 @@ testRun(void)
|
||||
TEST_RESULT_STR_Z(storage->path, "/repo", " check path");
|
||||
TEST_RESULT_STR(((StorageAzure *)storage->driver)->account, TEST_ACCOUNT_STR, " check account");
|
||||
TEST_RESULT_STR(((StorageAzure *)storage->driver)->container, TEST_CONTAINER_STR, " check container");
|
||||
TEST_RESULT_STR(((StorageAzure *)storage->driver)->sharedKey, TEST_KEY_SHARED_STR, " check key");
|
||||
TEST_RESULT_STR(
|
||||
strNewEncode(encodeBase64, ((StorageAzure *)storage->driver)->sharedKey), TEST_KEY_SHARED_STR, " check key");
|
||||
TEST_RESULT_STR_Z(((StorageAzure *)storage->driver)->host, TEST_ACCOUNT ".blob.core.windows.net", " check host");
|
||||
TEST_RESULT_STR_Z(((StorageAzure *)storage->driver)->pathPrefix, "/" TEST_CONTAINER, " check path prefix");
|
||||
TEST_RESULT_UINT(((StorageAzure *)storage->driver)->blockSize, STORAGE_AZURE_BLOCKSIZE_MIN, " check block size");
|
||||
|
||||
@@ -78,9 +78,9 @@ testRequest(IoWrite *write, Storage *s3, const char *verb, const char *path, Tes
|
||||
// Add md5
|
||||
if (param.content != NULL)
|
||||
{
|
||||
char md5Hash[HASH_TYPE_MD5_SIZE_HEX];
|
||||
encodeToStr(encodeBase64, bufPtr(cryptoHashOne(HASH_TYPE_MD5_STR, BUFSTRZ(param.content))), HASH_TYPE_M5_SIZE, md5Hash);
|
||||
strCatFmt(request, "content-md5:%s\r\n", md5Hash);
|
||||
strCatFmt(
|
||||
request, "content-md5:%s\r\n",
|
||||
strZ(strNewEncode(encodeBase64, cryptoHashOne(HASH_TYPE_MD5_STR, BUFSTRZ(param.content)))));
|
||||
}
|
||||
|
||||
// Add host
|
||||
|
||||
Reference in New Issue
Block a user