1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-30 05:39:12 +02:00

Accept leading tilde in paths for SFTP public/private keys.

The documentation indicates that leading tilde file paths for public/private keys are valid but the functionality was omitted from the original implementation.
This commit is contained in:
Reid Thompson 2023-08-08 03:41:34 -04:00 committed by GitHub
parent 1141dc2070
commit eb32d6de5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 5 deletions

View File

@ -28,6 +28,17 @@
<p>Multi-stanza check command.</p>
</release-item>
<release-item>
<github-pull-request id="2136"/>
<release-item-contributor-list>
<release-item-contributor id="reid.thompson"/>
<release-item-reviewer id="david.steele"/>
</release-item-contributor-list>
<p>Accept leading tilde in paths for SFTP public/private keys.</p>
</release-item>
<release-item>
<github-pull-request id="2072"/>

View File

@ -24,6 +24,9 @@ static struct
gid_t groupId; // Real group id of the calling process from getgid()
const String *groupName; // Group name if it exists
#ifdef HAVE_LIBSSH2
const String *userHome; // User home directory
#endif // HAVE_LIBSSH2
} userLocalData;
/**********************************************************************************************************************************/
@ -40,6 +43,9 @@ userInitInternal(void)
userLocalData.userId = getuid();
userLocalData.userName = userNameFromId(userLocalData.userId);
#ifdef HAVE_LIBSSH2
userLocalData.userHome = userHomeFromId(userLocalData.userId);
#endif // HAVE_LIBSSH2
userLocalData.userRoot = userLocalData.userId == 0;
userLocalData.groupId = getgid();
@ -114,6 +120,35 @@ groupNameFromId(gid_t groupId)
FUNCTION_TEST_RETURN(STRING, NULL);
}
/**********************************************************************************************************************************/
// Currently userHome() and userHomeFromId() are only used when building with libssh2
#ifdef HAVE_LIBSSH2
FN_EXTERN const String *
userHome(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN_CONST(STRING, userLocalData.userHome);
}
/**********************************************************************************************************************************/
FN_EXTERN String *
userHomeFromId(uid_t userId)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(UINT, userId);
FUNCTION_TEST_END();
struct passwd *userData = getpwuid(userId);
if (userData != NULL)
FUNCTION_TEST_RETURN(STRING, strNewZ(userData->pw_dir));
FUNCTION_TEST_RETURN(STRING, NULL);
}
#endif // HAVE_LIBSSH2
/**********************************************************************************************************************************/
FN_EXTERN uid_t
userId(void)

View File

@ -26,6 +26,16 @@ FN_EXTERN const String *groupName(void);
// Get the group name from a group id. Returns NULL if the group id is invalid or there is no mapping.
FN_EXTERN String *groupNameFromId(gid_t groupId);
#ifdef HAVE_LIBSSH2
// Get the home directory of the current user. Returns NULL if there is no mapping.
FN_EXTERN const String *userHome(void);
// Get the user home directory from a user id. Returns NULL if the user id is invalid or there is no mapping.
FN_EXTERN String *userHomeFromId(uid_t userId);
#endif // HAVE_LIBSSH2
// Get the id of the current user
FN_EXTERN uid_t userId(void);

View File

@ -10,6 +10,7 @@ SFTP Storage
#include "common/io/fd.h"
#include "common/io/socket/client.h"
#include "common/log.h"
#include "common/regExp.h"
#include "common/user.h"
#include "storage/sftp/read.h"
#include "storage/sftp/storage.intern.h"
@ -306,6 +307,26 @@ storageSftpInfo(THIS_VOID, const String *const file, const StorageInfoLevel leve
FUNCTION_LOG_RETURN(STORAGE_INFO, result);
}
/**********************************************************************************************************************************/
static String *
storageSftpExpandTildePath(const String *const tildePath)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, tildePath);
FUNCTION_TEST_END();
String *const result = strNew();
// Append to user home directory path substring after the tilde
MEM_CONTEXT_TEMP_BEGIN()
{
strCatFmt(result, "%s%s", strZ(userHome()), strZ(strSub(tildePath, (size_t)strChr(tildePath, '~') + 1)));
}
MEM_CONTEXT_TEMP_END();
FUNCTION_TEST_RETURN(STRING, result);
}
/**********************************************************************************************************************************/
// Helper function to get info for a file if it exists. This logic can't live directly in storageSftpList() because there is a race
// condition where a file might exist while listing the directory but it is gone before stat() can be called. In order to get
@ -877,13 +898,22 @@ storageSftpNew(
}
}
// Perform public key authorization, expand leading tilde key file paths if needed
String *const privKeyPath = regExpMatchOne(STRDEF("^ *~"), keyPriv) ? storageSftpExpandTildePath(keyPriv) : strDup(keyPriv);
String *const pubKeyPath =
param.keyPub != NULL && regExpMatchOne(STRDEF("^ *~"), param.keyPub) ?
storageSftpExpandTildePath(param.keyPub) : strDup(param.keyPub);
do
{
rc = libssh2_userauth_publickey_fromfile(
this->session, strZ(user), strZNull(param.keyPub), strZ(keyPriv), strZNull(param.keyPassphrase));
this->session, strZ(user), strZNull(pubKeyPath), strZ(privKeyPath), strZNull(param.keyPassphrase));
}
while (storageSftpWaitFd(this, rc));
strFree(privKeyPath);
strFree(pubKeyPath);
if (rc != 0)
{
if (rc == LIBSSH2_ERROR_EAGAIN)

View File

@ -30,6 +30,10 @@ testRun(void)
TEST_RESULT_UINT(groupIdFromName(STRDEF("bogus")), (uid_t)-1, "get bogus group id");
TEST_RESULT_STR(groupName(), TEST_GROUP_STR, "check name name");
TEST_RESULT_STR_Z(groupNameFromId(77777), NULL, "invalid group name by id");
TEST_RESULT_STR(userHome(), STRDEF("/home/" TEST_USER), "check user name");
TEST_RESULT_STR_Z(userHomeFromId(userId()), "/home/" TEST_USER, "user home by id");
TEST_RESULT_STR_Z(userHomeFromId(77777), NULL, "invalid user home by id");
}
FUNCTION_HARNESS_RETURN_VOID();

View File

@ -192,7 +192,7 @@ testRun(void)
ServiceError, "requested ssh2 hostkey hash type (aes-256-cbc) not available");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("public key from file auth failure");
TEST_TITLE("public key from file auth failure leading - tilde key paths");
hrnLibSsh2ScriptSet((HrnLibSsh2 [])
{
@ -212,7 +212,8 @@ testRun(void)
TEST_ERROR(
storageSftpNewP(
TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 1000, KEYPRIV, hashTypeSha1, .keyPub = KEYPUB,
TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 1000, STRDEF("~/.ssh/id_rsa"), hashTypeSha1,
.keyPub = STRDEF("~/.ssh/id_rsa.pub"),
.hostFingerprint = STRDEF("3132333435363738393039383736353433323130")),
ServiceError,
"public key authentication failed: libssh2 error [-16]\n"
@ -4577,8 +4578,8 @@ testRun(void)
hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp");
hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost");
hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1");
hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, KEYPRIV_CSTR);
hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, KEYPUB_CSTR);
hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, " ~/.ssh/id_rsa");
hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, " ~/.ssh/id_rsa.pub");
HRN_CFG_LOAD(cfgCmdArchiveGet, argList);
const Storage *storage = NULL;