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:
parent
1141dc2070
commit
eb32d6de5e
@ -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"/>
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user