diff --git a/src/build/config/config.yaml b/src/build/config/config.yaml index a8ff09b30f..181eb8e637 100644 --- a/src/build/config/config.yaml +++ b/src/build/config/config.yaml @@ -2424,6 +2424,14 @@ option: command: repo-type depend: repo-sftp-host + repo-sftp-identity-agent: + section: global + group: repo + type: string + required: false + command: repo-type + depend: repo-sftp-host + repo-sftp-known-host: section: global group: repo @@ -2439,7 +2447,8 @@ option: repo-sftp-private-key-file: section: global group: repo - type: string + type: list + required: false command: repo-type depend: repo-sftp-host @@ -2460,6 +2469,14 @@ option: command: repo-type depend: repo-sftp-host + repo-sftp-use-ssh-agent: + section: global + group: repo + type: boolean + default: true + command: repo-type + depend: repo-sftp-host + repo-storage-verify-tls: section: global group: repo diff --git a/src/build/help/help.xml b/src/build/help/help.xml index 8b9c94d7a5..03db73cb0b 100644 --- a/src/build/help/help.xml +++ b/src/build/help/help.xml @@ -1126,6 +1126,15 @@ pg-backup + + SFTP identity agent. + +

Specifies the UNIX-domain socket used to communicate with the authentication agent. This option overrides the SSH_AUTH_SOCK environment variable and can be used to select a specific agent. Arguments to repo-sftp-identity-agent may use tilde syntax to refer to a user's home directory. This option is not valid for versions of libssh2 prior to 1.9

+
+ + /var/lib/postgresql/.ssh/pgbackrest_ssh_identity_agent_socket +
+ SFTP known hosts file. @@ -1140,7 +1149,9 @@ SFTP private key file. -

SFTP private key file used for authentication.

+

SFTP private key file used for authentication. The {[dash]}-repo-sftp-private-key-file option can be passed multiple times to specify more than one private key file.

+

NOTE: If {[dash]}-repo-sftp-public-key-file is not specified, the public key path will be generated by appending .pub to the private key path and paired with it's private key for authentication. If it is specified, then it will be paired with each private key to attempt authentication.

+

NOTE: libssh2 versions before 1.9.0 expect a PEM format keypair, ssh-keygen -m PEM -t rsa -P will generate a PEM keypair without a passphrase.

~/.ssh/id_ed25519 @@ -1150,7 +1161,7 @@ SFTP private key passphrase. -

Passphrase used to access the private key. This is an optional feature when creating an SSH public/private key pair.

+

Passphrase used to access the private key. This is an optional feature when creating an SSH public/private key pair. If specified, it will be used with each key.

BeSureToGenerateAndUseASecurePassphrase @@ -1160,12 +1171,24 @@ SFTP public key file. -

SFTP public key file used for authentication. Optional if compiled against OpenSSL, required if compiled against a different library.

+

SFTP public key file used for authentication. Optional if compiled against OpenSSL, required if compiled against a different library. If a public key file is specified, it will be paired with each private key file during authentication.

+

NOTE: libssh2 versions before 1.9.0 expect a PEM format keypair, ssh-keygen -m PEM -t rsa -P will generate a PEM keypair without a passphrase.

~/.ssh/id_ed25519.pub
+ + SFTP use ssh agent. + + +

When enabled, if not already authenticated via a private key file, an attempt will be made to authenticate via ssh-agent. The default agent is read from the SSH_AUTH_SOCK environment variable. The default agent may be overridden by using the repo-sftp-identity-agent setting if compiled against libssh2 version 1.9 or greater.

+
+ + y + n +
+ Repository storage CA file. diff --git a/src/config/config.auto.h b/src/config/config.auto.h index cb9204c01f..661ce525f0 100644 --- a/src/config/config.auto.h +++ b/src/config/config.auto.h @@ -136,7 +136,7 @@ Option constants #define CFGOPT_TYPE "type" #define CFGOPT_VERBOSE "verbose" -#define CFG_OPTION_TOTAL 179 +#define CFG_OPTION_TOTAL 181 /*********************************************************************************************************************************** Option value constants @@ -524,10 +524,12 @@ typedef enum cfgOptRepoSftpHostKeyHashType, cfgOptRepoSftpHostPort, cfgOptRepoSftpHostUser, + cfgOptRepoSftpIdentityAgent, cfgOptRepoSftpKnownHost, cfgOptRepoSftpPrivateKeyFile, cfgOptRepoSftpPrivateKeyPassphrase, cfgOptRepoSftpPublicKeyFile, + cfgOptRepoSftpUseSshAgent, cfgOptRepoStorageCaFile, cfgOptRepoStorageCaPath, cfgOptRepoStorageHost, diff --git a/src/config/parse.auto.c.inc b/src/config/parse.auto.c.inc index 609baa1c24..35836901d9 100644 --- a/src/config/parse.auto.c.inc +++ b/src/config/parse.auto.c.inc @@ -8410,6 +8410,86 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ), // opt/repo-sftp-host-user ), // opt/repo-sftp-host-user // ----------------------------------------------------------------------------------------------------------------------------- + PARSE_RULE_OPTION // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_NAME("repo-sftp-identity-agent"), // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_TYPE(cfgOptTypeString), // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_RESET(true), // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_REQUIRED(false), // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_SECTION(cfgSectionGlobal), // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_GROUP_MEMBER(true), // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_GROUP_ID(cfgOptGrpRepo), // opt/repo-sftp-identity-agent + // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND_ROLE_MAIN_VALID_LIST // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdAnnotate) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdBackup) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdCheck) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdExpire) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdInfo) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdManifest) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoCreate) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoGet) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoLs) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoPut) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoRm) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRestore) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaCreate) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaDelete) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaUpgrade) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdVerify) // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND_ROLE_ASYNC_VALID_LIST // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdBackup) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRestore) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdVerify) // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND_ROLE_REMOTE_VALID_LIST // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdAnnotate) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdCheck) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdInfo) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdManifest) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoCreate) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoGet) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoLs) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoPut) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoRm) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRestore) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaCreate) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaDelete) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaUpgrade) // opt/repo-sftp-identity-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdVerify) // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + // opt/repo-sftp-identity-agent + PARSE_RULE_OPTIONAL // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_OPTIONAL_GROUP // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_OPTIONAL_DEPEND // opt/repo-sftp-identity-agent + ( // opt/repo-sftp-identity-agent + PARSE_RULE_VAL_OPT(cfgOptRepoType), // opt/repo-sftp-identity-agent + PARSE_RULE_VAL_STRID(parseRuleValStrIdSftp), // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + ), // opt/repo-sftp-identity-agent + // ----------------------------------------------------------------------------------------------------------------------------- PARSE_RULE_OPTION // opt/repo-sftp-known-host ( // opt/repo-sftp-known-host PARSE_RULE_OPTION_NAME("repo-sftp-known-host"), // opt/repo-sftp-known-host @@ -8495,10 +8575,11 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = PARSE_RULE_OPTION // opt/repo-sftp-private-key-file ( // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_NAME("repo-sftp-private-key-file"), // opt/repo-sftp-private-key-file - PARSE_RULE_OPTION_TYPE(cfgOptTypeString), // opt/repo-sftp-private-key-file + PARSE_RULE_OPTION_TYPE(cfgOptTypeList), // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_RESET(true), // opt/repo-sftp-private-key-file - PARSE_RULE_OPTION_REQUIRED(true), // opt/repo-sftp-private-key-file + PARSE_RULE_OPTION_REQUIRED(false), // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_SECTION(cfgSectionGlobal), // opt/repo-sftp-private-key-file + PARSE_RULE_OPTION_MULTI(true), // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_GROUP_MEMBER(true), // opt/repo-sftp-private-key-file PARSE_RULE_OPTION_GROUP_ID(cfgOptGrpRepo), // opt/repo-sftp-private-key-file // opt/repo-sftp-private-key-file @@ -8733,6 +8814,92 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] = ), // opt/repo-sftp-public-key-file ), // opt/repo-sftp-public-key-file // ----------------------------------------------------------------------------------------------------------------------------- + PARSE_RULE_OPTION // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_NAME("repo-sftp-use-ssh-agent"), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_TYPE(cfgOptTypeBoolean), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_NEGATE(true), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_RESET(true), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_REQUIRED(true), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_SECTION(cfgSectionGlobal), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_GROUP_MEMBER(true), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_GROUP_ID(cfgOptGrpRepo), // opt/repo-sftp-use-ssh-agent + // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND_ROLE_MAIN_VALID_LIST // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdAnnotate) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdBackup) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdCheck) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdExpire) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdInfo) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdManifest) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoCreate) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoGet) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoLs) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoPut) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoRm) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRestore) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaCreate) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaDelete) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaUpgrade) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdVerify) // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND_ROLE_ASYNC_VALID_LIST // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND_ROLE_LOCAL_VALID_LIST // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdBackup) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRestore) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdVerify) // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND_ROLE_REMOTE_VALID_LIST // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdAnnotate) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchiveGet) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdArchivePush) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdCheck) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdInfo) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdManifest) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoCreate) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoGet) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoLs) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoPut) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRepoRm) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdRestore) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaCreate) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaDelete) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdStanzaUpgrade) // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTION_COMMAND(cfgCmdVerify) // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTIONAL // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTIONAL_GROUP // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTIONAL_DEPEND // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_VAL_OPT(cfgOptRepoType), // opt/repo-sftp-use-ssh-agent + PARSE_RULE_VAL_STRID(parseRuleValStrIdSftp), // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + // opt/repo-sftp-use-ssh-agent + PARSE_RULE_OPTIONAL_DEFAULT // opt/repo-sftp-use-ssh-agent + ( // opt/repo-sftp-use-ssh-agent + PARSE_RULE_VAL_BOOL_TRUE, // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + ), // opt/repo-sftp-use-ssh-agent + // ----------------------------------------------------------------------------------------------------------------------------- PARSE_RULE_OPTION // opt/repo-storage-ca-file ( // opt/repo-storage-ca-file PARSE_RULE_OPTION_NAME("repo-storage-ca-file"), // opt/repo-storage-ca-file @@ -10984,10 +11151,12 @@ static const uint8_t optionResolveOrder[] = cfgOptRepoSftpHostKeyHashType, // opt-resolve-order cfgOptRepoSftpHostPort, // opt-resolve-order cfgOptRepoSftpHostUser, // opt-resolve-order + cfgOptRepoSftpIdentityAgent, // opt-resolve-order cfgOptRepoSftpKnownHost, // opt-resolve-order cfgOptRepoSftpPrivateKeyFile, // opt-resolve-order cfgOptRepoSftpPrivateKeyPassphrase, // opt-resolve-order cfgOptRepoSftpPublicKeyFile, // opt-resolve-order + cfgOptRepoSftpUseSshAgent, // opt-resolve-order cfgOptRepoStorageCaFile, // opt-resolve-order cfgOptRepoStorageCaPath, // opt-resolve-order cfgOptRepoStorageHost, // opt-resolve-order diff --git a/src/storage/sftp/helper.c b/src/storage/sftp/helper.c index 7a1321a226..33c62ad05b 100644 --- a/src/storage/sftp/helper.c +++ b/src/storage/sftp/helper.c @@ -27,19 +27,21 @@ storageSftpHelper(const unsigned int repoIdx, const bool write, StoragePathExpre MEM_CONTEXT_TEMP_BEGIN() { const StringList *const knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)); + const StringList *const privKeys = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)); MEM_CONTEXT_PRIOR_BEGIN() { result = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), - cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .write = write, - .pathExpressionFunction = pathExpressionCallback, .modeFile = STORAGE_MODE_FILE_DEFAULT, + cfgOptionUInt64(cfgOptIoTimeout), privKeys, cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), + .write = write, .pathExpressionFunction = pathExpressionCallback, .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), - .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), .knownHosts = knownHosts); + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx), .knownHosts = knownHosts); } MEM_CONTEXT_PRIOR_END(); } diff --git a/src/storage/sftp/storage.c b/src/storage/sftp/storage.c index c592c208e3..a57f7df7ea 100644 --- a/src/storage/sftp/storage.c +++ b/src/storage/sftp/storage.c @@ -36,6 +36,7 @@ struct StorageSftp LIBSSH2_SFTP *sftpSession; // LibSsh2 session sftp session LIBSSH2_SFTP_HANDLE *sftpHandle; // LibSsh2 session sftp handle TimeMSec timeout; // Session timeout + LIBSSH2_AGENT *agent; // LibSsh2 ssh agent handle }; /*********************************************************************************************************************************** @@ -308,6 +309,17 @@ storageSftpLibSsh2SessionFreeResource(THIS_VOID) } } + if (this->agent) + { + rc = libssh2_agent_disconnect(this->agent); + + if (rc != 0) + THROW_FMT(ServiceError, "failed to disconnect libssh2 ssh2 agent: libssh2 errno [%d]", rc); + + // Function returns void + libssh2_agent_free(this->agent); + } + if (this->session != NULL) { do @@ -528,6 +540,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); +} + /*********************************************************************************************************************************** Build known hosts file list. If knownHosts is empty build the default file list, otherwise build the list provided. knownHosts requires full path and/or leading tilde path entries. @@ -561,9 +593,8 @@ storageSftpKnownHostsFilesList(const StringList *const knownHosts) if (strBeginsWithZ(filePath, "~/")) { - // Replace leading tilde with space, trim space, prepend user home path and add to the result list - strLstAddFmt( - result, "%s%s", strZ(userHome()), strZ(strTrim(strSub(filePath, (size_t)strChr(filePath, '~') + 1)))); + // Expand leading tilde and add to the result list + strLstAddFmt(result, "%s", strZ(storageSftpExpandTildePath(filePath))); } else strLstAdd(result, filePath); @@ -575,24 +606,36 @@ storageSftpKnownHostsFilesList(const StringList *const knownHosts) FUNCTION_LOG_RETURN(STRING_LIST, result); } -/**********************************************************************************************************************************/ -static String * -storageSftpExpandTildePath(const String *const tildePath) +/*********************************************************************************************************************************** +Build private key file list. privKeys requires full path and/or leading tilde path entries. +***********************************************************************************************************************************/ +static StringList * +storageSftpIdentityFilesList(const StringList *const privKeys) { - FUNCTION_TEST_BEGIN(); - FUNCTION_TEST_PARAM(STRING, tildePath); - FUNCTION_TEST_END(); + FUNCTION_LOG_BEGIN(logLevelDebug); + FUNCTION_LOG_PARAM(STRING_LIST, privKeys); + FUNCTION_LOG_END(); - String *const result = strNew(); + StringList *const result = strLstNew(); - // 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))); + // Process the privKey file list entries and add them to the result list + for (unsigned int listIdx = 0; listIdx < strLstSize(privKeys); listIdx++) + { + // Get the trimmed file path and add it to the result list + const String *const filePath = strTrim(strLstGet(privKeys, listIdx)); + + // Expand leading tilde and add to the result list + if (strBeginsWithZ(filePath, "~/")) + strLstAddFmt(result, "%s", strZ(storageSftpExpandTildePath(filePath))); + else + strLstAdd(result, filePath); + } } MEM_CONTEXT_TEMP_END(); - FUNCTION_TEST_RETURN(STRING, result); + FUNCTION_LOG_RETURN(STRING_LIST, result); } /**********************************************************************************************************************************/ @@ -1081,7 +1124,7 @@ static const StorageInterface storageInterfaceSftp = FN_EXTERN Storage * storageSftpNew( const String *const path, const String *const host, const unsigned int port, const String *const user, - const TimeMSec timeout, const String *const keyPriv, const StringId hostKeyHashType, const StorageSftpNewParam param) + const TimeMSec timeout, const StringList *const privKeys, const StringId hostKeyHashType, const StorageSftpNewParam param) { FUNCTION_LOG_BEGIN(logLevelDebug); FUNCTION_LOG_PARAM(STRING, path); @@ -1089,24 +1132,25 @@ storageSftpNew( FUNCTION_LOG_PARAM(UINT, port); FUNCTION_LOG_PARAM(STRING, user); FUNCTION_LOG_PARAM(TIME_MSEC, timeout); - FUNCTION_LOG_PARAM(STRING, keyPriv); + FUNCTION_LOG_PARAM(STRING_LIST, privKeys); FUNCTION_LOG_PARAM(STRING_ID, hostKeyHashType); + FUNCTION_LOG_PARAM(STRING, param.hostFingerprint); + FUNCTION_LOG_PARAM(STRING_ID, param.hostKeyCheckType); + FUNCTION_LOG_PARAM(STRING, param.identityAgent); FUNCTION_LOG_PARAM(STRING, param.keyPub); FUNCTION_TEST_PARAM(STRING, param.keyPassphrase); - FUNCTION_LOG_PARAM(STRING_ID, param.hostKeyCheckType); - FUNCTION_LOG_PARAM(STRING, param.hostFingerprint); FUNCTION_LOG_PARAM(STRING_LIST, param.knownHosts); FUNCTION_LOG_PARAM(MODE, param.modeFile); FUNCTION_LOG_PARAM(MODE, param.modePath); - FUNCTION_LOG_PARAM(BOOL, param.write); FUNCTION_LOG_PARAM(FUNCTIONP, param.pathExpressionFunction); + FUNCTION_LOG_PARAM(BOOL, param.useSshAgent); + FUNCTION_LOG_PARAM(BOOL, param.write); FUNCTION_LOG_END(); ASSERT(path != NULL); ASSERT(host != NULL); ASSERT(port != 0); ASSERT(user != NULL); - ASSERT(keyPriv != NULL); ASSERT(hostKeyHashType != 0); // Initialize user module userInit(); @@ -1315,35 +1359,154 @@ storageSftpNew( libssh2_knownhost_free(knownHostsList); } - // Perform public key authorization, expand leading tilde key file paths if needed - String *const privKeyPath = regExpMatchOne(STRDEF("^ *~"), keyPriv) ? storageSftpExpandTildePath(keyPriv) : strDup(keyPriv); + // Attempt to authenticate with any provided private keys + // Build/normalize private keys list + StringList *const privateKeys = storageSftpIdentityFilesList(privKeys); + + // If provided a public key normalize it if necessary String *const pubKeyPath = - param.keyPub != NULL && regExpMatchOne(STRDEF("^ *~"), param.keyPub) ? - storageSftpExpandTildePath(param.keyPub) : strDup(param.keyPub); + param.keyPub != NULL && + regExpMatchOne(STRDEF("^ *~"), param.keyPub) ? storageSftpExpandTildePath(param.keyPub) : strDup(param.keyPub); - do + bool authSuccess = false; + + if (!strLstEmpty(privateKeys)) { - rc = libssh2_userauth_publickey_fromfile( - this->session, strZ(user), strZNull(pubKeyPath), strZ(privKeyPath), strZNull(param.keyPassphrase)); + // Attempt to authenticate with each private key + for (unsigned int listIdx = 0; listIdx < strLstSize(privateKeys); listIdx++) + { + const String *const privateKey = strLstGet(privateKeys, listIdx); + + // If a public key has been provided use only that public key, otherwise use the private key with a .pub extension + do + { + rc = libssh2_userauth_publickey_fromfile( + this->session, strZ(user), + pubKeyPath != NULL ? strZ(pubKeyPath) : strZ(strCatFmt(strNew(), "%s.pub", strZ(privateKey))), + strZ(privateKey), strZNull(param.keyPassphrase)); + } + while (storageSftpWaitFd(this, rc)); + + // Log the result of the authentication attempt + if (rc != 0) + { + if (rc == LIBSSH2_ERROR_EAGAIN) + LOG_DETAIL_FMT("timeout during public key authentication"); + else + { + LOG_DETAIL_FMT( + "public key authentication with username %s and key %s failed [%d]", strZ(user), strZ(privateKey), rc); + } + } + else + { + authSuccess = true; + + LOG_DETAIL_FMT("public key authentication with username %s and key %s succeeded", strZ(user), strZ(privateKey)); + break; + } + } } - while (storageSftpWaitFd(this, rc)); - strFree(privKeyPath); + // Free private key list and public key path + strLstFree(privateKeys); strFree(pubKeyPath); - if (rc != 0) + // Attempt to authenticate with agent if not authenticated and agent enabled + if (authSuccess == false && param.useSshAgent == true) { - if (rc == LIBSSH2_ERROR_EAGAIN) - THROW_FMT(ServiceError, "timeout during public key authentication"); + // Init the libssh2 agent + this->agent = libssh2_agent_init(this->session); + + char *ssh2ErrMsg; + int ssh2ErrMsgLen; + + if (this->agent == NULL) + { + rc = libssh2_session_last_error(this->session, &ssh2ErrMsg, &ssh2ErrMsgLen, 0); + + THROW_FMT(ServiceError, "failure initializing ssh-agent support [%d]: %s", rc, ssh2ErrMsg); + } + + // If a specific ssh agent path has been requested, set it for the agent + if (param.identityAgent != NULL) + { + // Does the version of libssh2 (>= 1.9.0) support the libssh2_agent_set_identity_path function +#if LIBSSH2_VERSION_NUM >= 0x010900 + libssh2_agent_set_identity_path( + this->agent, + regExpMatchOne(STRDEF("^ *~"), param.identityAgent) ? + strZ(storageSftpExpandTildePath(param.identityAgent)) : strZ(strTrim(strDup(param.identityAgent)))); +#else + THROW_FMT( + ServiceError, + "libssh2 version %s does not support ssh-agent identity path, requires version 1.9 or greater", + libssh2_version(0)); +#endif + } + + // Attempt to connect to the agent + if ((rc = libssh2_agent_connect(this->agent)) != 0) + { + rc = libssh2_session_last_error(this->session, &ssh2ErrMsg, &ssh2ErrMsgLen, 0); + + THROW_FMT( + ServiceError, + "failure connecting to ssh-agent %s[%d]%s", +#if LIBSSH2_VERSION_NUM >= 0x010900 + param.identityAgent == NULL ? "" : zNewFmt("'%s' ", strZ(param.identityAgent)), +#else + "", +#endif + rc, zNewFmt(": %s", ssh2ErrMsg)); + } + if ((rc = libssh2_agent_list_identities(this->agent)) != 0) + THROW_FMT(ServiceError, "failure requesting identities to ssh-agent [%d]", rc); + + // Loop through the identities and attempt to authenticate with each + struct libssh2_agent_publickey *identity, *prev_identity = NULL; + + for (;;) + { + rc = libssh2_agent_get_identity(this->agent, &identity, prev_identity); + + // Break if we've reached the end of the public keys + if (rc == 1) + break; + + // Throw an error if libssh2_agent_get_identity errored + if (rc < 0) + THROW_FMT(ServiceError, "failure obtaining identity from ssh-agent [%d]", rc); + + // Attempt to authenticate with the current identity + do + { + rc = libssh2_agent_userauth(this->agent, strZ(user), identity); + } + while (storageSftpWaitFd(this, rc)); + + // Log the result of the authentication attempt + if (rc != 0) + LOG_DETAIL_FMT("ssh-agent authentication with username %s failed [%d]", strZ(user), rc); + else + { + authSuccess = true; + + LOG_DETAIL_FMT("ssh-agent authentication with username %s succeeded", strZ(user)); + break; + } + + prev_identity = identity; + } + } + + if (authSuccess == false) + { storageSftpEvalLibSsh2Error( rc, libssh2_sftp_last_error(this->sftpSession), &ServiceError, - STRDEF("public key authentication failed"), - STRDEF( - "HINT: libssh2 compiled against non-openssl libraries requires --repo-sftp-private-key-file and" - " --repo-sftp-public-key-file to be provided\n" - "HINT: libssh2 versions before 1.9.0 expect a PEM format keypair, try ssh-keygen -m PEM -t rsa -P \"\" to" - " generate the keypair")); + rc != 1 ? STRDEF("ssh authentication failed") : STRDEF("ssh authentication failed, reached end of public keys"), + NULL); } // Init the sftp session diff --git a/src/storage/sftp/storage.h b/src/storage/sftp/storage.h index 5d9a558824..06902fd1f2 100644 --- a/src/storage/sftp/storage.h +++ b/src/storage/sftp/storage.h @@ -35,14 +35,16 @@ typedef struct StorageSftpNewParam const String *keyPassphrase; StringId hostKeyCheckType; const String *hostFingerprint; + const String *identityAgent; const StringList *knownHosts; + const bool useSshAgent; } StorageSftpNewParam; -#define storageSftpNewP(path, host, port, user, timeout, keyPriv, hostKeyHashType, ...) \ - storageSftpNew(path, host, port, user, timeout, keyPriv, hostKeyHashType, (StorageSftpNewParam){VAR_PARAM_INIT, __VA_ARGS__}) +#define storageSftpNewP(path, host, port, user, timeout, privKeys, hostKeyHashType, ...) \ + storageSftpNew(path, host, port, user, timeout, privKeys, hostKeyHashType, (StorageSftpNewParam){VAR_PARAM_INIT, __VA_ARGS__}) FN_EXTERN Storage *storageSftpNew( - const String *path, const String *host, unsigned int port, const String *user, TimeMSec timeout, const String *keyPriv, + const String *path, const String *host, unsigned int port, const String *user, TimeMSec timeout, const StringList *privKeys, StringId hostKeyHashType, const StorageSftpNewParam param); #endif // HAVE_LIBSSH2 diff --git a/test/src/common/harnessLibSsh2.c b/test/src/common/harnessLibSsh2.c index 6436a0ecb1..80b331c10b 100644 --- a/test/src/common/harnessLibSsh2.c +++ b/test/src/common/harnessLibSsh2.c @@ -154,6 +154,114 @@ hrnLibSsh2ScriptRun(const char *const function, const VariantList *const param, return result; } +/*********************************************************************************************************************************** +Shim for libssh2_agent_init +***********************************************************************************************************************************/ +LIBSSH2_AGENT * +libssh2_agent_init(LIBSSH2_SESSION *session) +{ + HrnLibSsh2 *hrnLibSsh2 = hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_INIT, NULL, (HrnLibSsh2 *)session); + + return hrnLibSsh2->resultNull ? NULL : (LIBSSH2_AGENT *)hrnLibSsh2; +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_connect +***********************************************************************************************************************************/ +int +libssh2_agent_connect(LIBSSH2_AGENT *agent) +{ + return hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_CONNECT, NULL, (HrnLibSsh2 *)agent)->resultInt; +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_disconnect +***********************************************************************************************************************************/ +int +libssh2_agent_disconnect(LIBSSH2_AGENT *agent) +{ + return hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_DISCONNECT, NULL, (HrnLibSsh2 *)agent)->resultInt; +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_free +***********************************************************************************************************************************/ +void +libssh2_agent_free(LIBSSH2_AGENT *agent) +{ + if (agent == NULL) + { + snprintf( + hrnLibSsh2ScriptError, sizeof(hrnLibSsh2ScriptError), + "libssh2 script function 'libssh2_agent_free', expects agent to be not NULL"); + THROW(AssertError, hrnLibSsh2ScriptError); + } + + hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_FREE, NULL, (HrnLibSsh2 *)agent); +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_get_identity +***********************************************************************************************************************************/ +int +libssh2_agent_get_identity(LIBSSH2_AGENT *agent, struct libssh2_agent_publickey **store, struct libssh2_agent_publickey *prev) +{ + // Avoid compiler complaining of unused params + (void)prev; + (void)store; + + HrnLibSsh2 *hrnLibSsh2 = hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_GET_IDENTITY, NULL, (HrnLibSsh2 *)agent); + + return hrnLibSsh2->resultInt; +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_get_identity_path +***********************************************************************************************************************************/ +const char * +libssh2_agent_get_identity_path(LIBSSH2_AGENT *agent) +{ + HrnLibSsh2 *hrnLibSsh2 = hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_GET_IDENTITY_PATH, NULL, (HrnLibSsh2 *)agent); + + return hrnLibSsh2->identity_agent == NULL ? NULL : hrnLibSsh2->identity_agent; +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_list_identities +***********************************************************************************************************************************/ +int +libssh2_agent_list_identities(LIBSSH2_AGENT *agent) +{ + return hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_LIST_IDENTITIES, NULL, (HrnLibSsh2 *)agent)->resultInt; +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_set_identity_path +***********************************************************************************************************************************/ +void +libssh2_agent_set_identity_path(LIBSSH2_AGENT *agent, const char *path) +{ + // Avoid compiler complaining of unused param + (void)path; + + hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_SET_IDENTITY_PATH, NULL, (HrnLibSsh2 *)agent); +} + +/*********************************************************************************************************************************** +Shim for libssh2_agent_userauth +***********************************************************************************************************************************/ +int +libssh2_agent_userauth(LIBSSH2_AGENT *agent, const char *username, struct libssh2_agent_publickey *identity) +{ + // Avoid compiler complaining of unused params + (void)username; + (void)identity; + + HrnLibSsh2 *hrnLibSsh2 = hrnLibSsh2ScriptRun(HRNLIBSSH2_AGENT_USERAUTH, NULL, (HrnLibSsh2 *)agent); + + return hrnLibSsh2->resultInt; +} + /*********************************************************************************************************************************** Shim for libssh2_init ***********************************************************************************************************************************/ diff --git a/test/src/common/harnessLibSsh2.h b/test/src/common/harnessLibSsh2.h index c17377eae8..16689c7bce 100644 --- a/test/src/common/harnessLibSsh2.h +++ b/test/src/common/harnessLibSsh2.h @@ -34,6 +34,15 @@ libssh2 authorization constants /*********************************************************************************************************************************** Function constants ***********************************************************************************************************************************/ +#define HRNLIBSSH2_AGENT_INIT "libssh2_agent_init" +#define HRNLIBSSH2_AGENT_CONNECT "libssh2_agent_connect" +#define HRNLIBSSH2_AGENT_DISCONNECT "libssh2_agent_disconnect" +#define HRNLIBSSH2_AGENT_FREE "libssh2_agent_free" +#define HRNLIBSSH2_AGENT_GET_IDENTITY "libssh2_agent_get_identity" +#define HRNLIBSSH2_AGENT_GET_IDENTITY_PATH "libssh2_agent_get_identity_path" +#define HRNLIBSSH2_AGENT_LIST_IDENTITIES "libssh2_agent_list_identities" +#define HRNLIBSSH2_AGENT_SET_IDENTITY_PATH "libssh2_agent_set_identity_path" +#define HRNLIBSSH2_AGENT_USERAUTH "libssh2_agent_userauth" #define HRNLIBSSH2_HOSTKEY_HASH "libssh2_hostkey_hash" #define HRNLIBSSH2_INIT "libssh2_init" #define HRNLIBSSH2_KNOWNHOST_ADDC "libssh2_knownhost_addc" @@ -123,6 +132,7 @@ typedef struct HrnLibSsh2 const String *symlinkExTarget; // libssh2_sftp_symlink_ex target const String *fileName; // libssh2_readdir* libssh2_stat* filename const String *readBuffer; // what to copy into read buffer + const char *identity_agent; // libssh2 identity agent path TimeMSec sleep; // Sleep specified milliseconds before returning from function size_t len; // libssh2_session_hostkey len int type; // libssh2_session_hostkey type diff --git a/test/src/module/command/helpTest.c b/test/src/module/command/helpTest.c index b37879752b..8fff72a88a 100644 --- a/test/src/module/command/helpTest.c +++ b/test/src/module/command/helpTest.c @@ -328,10 +328,12 @@ testRun(void) " --repo-sftp-host-key-hash-type SFTP repository host key hash type\n" " --repo-sftp-host-port SFTP repository host port [default=22]\n" " --repo-sftp-host-user SFTP repository host user\n" + " --repo-sftp-identity-agent SFTP identity agent\n" " --repo-sftp-known-host SFTP known hosts file\n" " --repo-sftp-private-key-file SFTP private key file\n" " --repo-sftp-private-key-passphrase SFTP private key passphrase\n" " --repo-sftp-public-key-file SFTP public key file\n" + " --repo-sftp-use-ssh-agent SFTP use ssh agent [default=y]\n" " --repo-storage-ca-file repository storage CA file\n" " --repo-storage-ca-path repository storage CA path\n" " --repo-storage-host repository storage host\n" diff --git a/test/src/module/storage/sftpTest.c b/test/src/module/storage/sftpTest.c index 4846e417b4..a3e645b87f 100644 --- a/test/src/module/storage/sftpTest.c +++ b/test/src/module/storage/sftpTest.c @@ -66,6 +66,10 @@ testRun(void) // Install shim to manage true/false return for fdReady hrnFdReadyShimInstall(); + // Build default test private key list + StringList *privKeyList = strLstNew(); + strLstAdd(privKeyList, KEYPRIV); + // Directory and file that cannot be accessed to test permissions errors const String *fileNoPerm = STRDEF(TEST_PATH "/noperm/noperm"); String *pathNoPerm = strPath(fileNoPerm); @@ -91,7 +95,7 @@ testRun(void) TEST_ERROR( storageSftpNewP( - TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 5, KEYPRIV, hashTypeSha1, .keyPub = KEYPUB, + TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 5, privKeyList, hashTypeSha1, .keyPub = KEYPUB, .hostKeyCheckType = SFTP_STRICT_HOSTKEY_CHECKING_STRICT), ServiceError, "unable to init libssh2"); @@ -107,7 +111,7 @@ testRun(void) TEST_ERROR( storageSftpNewP( - TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 5, KEYPRIV, hashTypeSha1, .keyPub = KEYPUB, + TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 5, privKeyList, hashTypeSha1, .keyPub = KEYPUB, .hostKeyCheckType = SFTP_STRICT_HOSTKEY_CHECKING_STRICT), ServiceError, "unable to init libssh2 session"); @@ -128,7 +132,7 @@ 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, privKeyList, hashTypeSha1, .keyPub = KEYPUB, .hostKeyCheckType = SFTP_STRICT_HOSTKEY_CHECKING_STRICT), ServiceError, "libssh2 handshake failed [-45]: Bad socket provided"); @@ -148,7 +152,7 @@ testRun(void) TEST_ERROR( storageSftpNewP( - TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 100, KEYPRIV, hashTypeSha1, .keyPub = KEYPUB, + TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 100, privKeyList, hashTypeSha1, .keyPub = KEYPUB, .hostKeyCheckType = SFTP_STRICT_HOSTKEY_CHECKING_STRICT), ServiceError, "timeout during libssh2 handshake [-37]"); @@ -167,7 +171,7 @@ 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, privKeyList, hashTypeSha1, .keyPub = KEYPUB, .hostFingerprint = STRDEF("3132333435363738393039383736353433323130"), .hostKeyCheckType = SFTP_STRICT_HOSTKEY_CHECKING_FINGERPRINT), ServiceError, "libssh2 hostkey hash failed: libssh2 errno [-7]"); @@ -185,7 +189,7 @@ testRun(void) TEST_ERROR( storageSftpNewP( - TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 20, KEYPRIV, cipherTypeAes256Cbc, .keyPub = KEYPUB, + TEST_PATH_STR, STRDEF("localhost"), 22, TEST_USER_STR, 20, privKeyList, cipherTypeAes256Cbc, .keyPub = KEYPUB, .write = true, .hostKeyCheckType = SFTP_STRICT_HOSTKEY_CHECKING_STRICT), ServiceError, "requested ssh2 hostkey hash type (aes-256-cbc) not available"); @@ -204,6 +208,12 @@ testRun(void) {.function = HRNLIBSSH2_SESSION_BLOCK_DIRECTIONS, .resultInt = SSH2_NO_BLOCK_READING_WRITING}, {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", .resultInt = -16}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = -1}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = 1}, // 1 == reached the end of public keys list {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = LIBSSH2_FX_OK}, {.function = NULL} }); @@ -228,19 +238,16 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), - .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx))), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), ServiceError, - "public key authentication failed: libssh2 error [-16]\n" - "HINT: libssh2 compiled against non-openssl libraries requires --repo-sftp-private-key-file and" - " --repo-sftp-public-key-file to be provided\n" - "HINT: libssh2 versions before 1.9.0 expect a PEM format keypair, try ssh-keygen -m PEM -t rsa -P \"\" to generate the" - " keypair"); + "ssh authentication failed, reached end of public keys: libssh2 error [1]"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("fingerprint mismatch"); @@ -273,17 +280,588 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), - .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx))), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), ServiceError, "host [3132333435363738393039383736353433323130] and configured fingerprint (repo-sftp-host-fingerprint)" " [9132333435363738393039383736353433323130] do not match"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_init failure"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT, .resultNull = true}, + {.function = HRNLIBSSH2_SESSION_LAST_ERROR, .errMsg = (char *)"Unable to allocate space for agent connection", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = NULL} + }); + + // Load configuration + argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + hrnCfgArgRawZ(argList, cfgOptRepo, "1"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostUser, TEST_USER); + hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyCheckType, "fingerprint"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, "~/.ssh/id_rsa"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, "~/.ssh/id_rsa.pub"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostFingerprint, "3132333435363738393039383736353433323130"); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "failure initializing ssh-agent support [-6]: Unable to allocate space for agent connection"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_connect failure"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_BAD_USE}, + {.function = HRNLIBSSH2_SESSION_LAST_ERROR, .errMsg = (char *)"no auth sock variable", + .resultInt = LIBSSH2_ERROR_BAD_USE}, + {.function = NULL} + }); + + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "failure connecting to ssh-agent [-39]: no auth sock variable"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_connect failure - non default agent"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, +#if LIBSSH2_VERSION_NUM >= 0x010900 + {.function = HRNLIBSSH2_AGENT_SET_IDENTITY_PATH}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_AGENT_PROTOCOL}, + {.function = HRNLIBSSH2_SESSION_LAST_ERROR, .errMsg = (char *)"failed connecting with agent", + .resultInt = LIBSSH2_ERROR_AGENT_PROTOCOL}, +#endif + {.function = NULL} + }); + + // Load configuration + argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + hrnCfgArgRawZ(argList, cfgOptRepo, "1"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostUser, TEST_USER); + hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyCheckType, "fingerprint"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, "~/.ssh/id_rsa"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, "~/.ssh/id_rsa.pub"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostFingerprint, "3132333435363738393039383736353433323130"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpIdentityAgent, "/tmp/pgbackrest-ssh-agent"); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); +#if LIBSSH2_VERSION_NUM >= 0x010900 + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "failure connecting to ssh-agent '/tmp/pgbackrest-ssh-agent' [-42]: failed connecting with agent"); +#else + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "libssh2 version " LIBSSH2_VERSION " does not support ssh-agent identity path, requires version 1.9 or greater"); +#endif + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_list_identities failure"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = -1}, + {.function = NULL} + }); + + // Load configuration + argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + hrnCfgArgRawZ(argList, cfgOptRepo, "1"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostUser, TEST_USER); + hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyCheckType, "fingerprint"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, "~/.ssh/id_rsa"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, "~/.ssh/id_rsa.pub"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostFingerprint, "3132333435363738393039383736353433323130"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpUseSshAgent, "y"); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "failure requesting identities to ssh-agent [-1]"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_get_identity failure"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = -1}, + {.function = NULL} + }); + + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "failure obtaining identity from ssh-agent [-1]"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_userauth failure"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = 1}, + {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = LIBSSH2_FX_OK}, + {.function = NULL} + }); + + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "ssh authentication failed, reached end of public keys: libssh2 error [1]"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_userauth success - libssh2_agent_disconnect failure in free resources"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SFTP_INIT}, + {.function = HRNLIBSSH2_SFTP_SHUTDOWN, .resultInt = 0}, + {.function = HRNLIBSSH2_AGENT_DISCONNECT, .resultInt = -1}, + {.function = NULL} + }); + + // Load configuration + argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + hrnCfgArgRawZ(argList, cfgOptRepo, "1"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, "/tmp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostUser, TEST_USER); + hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyCheckType, "fingerprint"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, "~/.ssh/id_rsa"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, "~/.ssh/id_rsa.pub"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostFingerprint, "3132333435363738393039383736353433323130"); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + + Storage *storageTest = NULL; + + TEST_ASSIGN( + storageTest, + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + "new storage (defaults)"); + TEST_ERROR_FMT( + memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))), + ServiceError, + "failed to disconnect libssh2 ssh2 agent: libssh2 errno [-1]"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_userauth success"); + + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = LIBSSH2_ERROR_EAGAIN}, + {.function = HRNLIBSSH2_SESSION_BLOCK_DIRECTIONS, .resultInt = SSH2_BLOCK_READING}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SFTP_INIT}, + {.function = HRNLIBSSH2_SFTP_SHUTDOWN, .resultInt = 0}, + {.function = HRNLIBSSH2_AGENT_DISCONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_FREE}, + {.function = HRNLIBSSH2_SESSION_DISCONNECT_EX, .param = "[11,\"pgBackRest instance shutdown\",\"\"]", .resultInt = 0}, + {.function = HRNLIBSSH2_SESSION_FREE, .resultInt = 0}, + {.function = NULL} + }); + + storageTest = NULL; + + TEST_ASSIGN( + storageTest, + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + "new storage (defaults)"); + + memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_userauth success - identityAgent populated tilde path"); + + // Load configuration + argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + hrnCfgArgRawZ(argList, cfgOptRepo, "1"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, "/tmp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostUser, TEST_USER); + hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyCheckType, "fingerprint"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, "~/.ssh/id_rsa"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, "~/.ssh/id_rsa.pub"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostFingerprint, "3132333435363738393039383736353433323130"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpIdentityAgent, "~/.ssh/myagent"); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + +#if LIBSSH2_VERSION_NUM >= 0x010900 + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_SET_IDENTITY_PATH}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SFTP_INIT}, + {.function = HRNLIBSSH2_SFTP_SHUTDOWN, .resultInt = 0}, + {.function = HRNLIBSSH2_AGENT_DISCONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_FREE}, + {.function = HRNLIBSSH2_SESSION_DISCONNECT_EX, .param = "[11,\"pgBackRest instance shutdown\",\"\"]", .resultInt = 0}, + {.function = HRNLIBSSH2_SESSION_FREE, .resultInt = 0}, + {.function = NULL} + }); + + storageTest = NULL; + + TEST_ASSIGN( + storageTest, + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + "new storage (defaults)"); + + memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); +#else + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", + .resultInt = LIBSSH2_ERROR_ALLOC}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = NULL} + }); + + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "libssh2 version " LIBSSH2_VERSION " does not support ssh-agent identity path, requires version 1.9 or greater"); +#endif + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("libssh2_agent_userauth success - identityAgent populated full path"); + + // Load configuration + argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + hrnCfgArgRawZ(argList, cfgOptRepo, "1"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, "/tmp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostUser, TEST_USER); + hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyCheckType, "fingerprint"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostFingerprint, "3132333435363738393039383736353433323130"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpIdentityAgent, "/var/lib/postgresql/.ssh/myagent"); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + +#if LIBSSH2_VERSION_NUM >= 0x010900 + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = HRNLIBSSH2_AGENT_SET_IDENTITY_PATH}, + {.function = HRNLIBSSH2_AGENT_CONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_LIST_IDENTITIES, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_GET_IDENTITY, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = LIBSSH2_ERROR_EAGAIN}, + {.function = HRNLIBSSH2_SESSION_BLOCK_DIRECTIONS, .resultInt = SSH2_BLOCK_READING}, + {.function = HRNLIBSSH2_AGENT_USERAUTH, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SFTP_INIT}, + {.function = HRNLIBSSH2_SFTP_SHUTDOWN, .resultInt = 0}, + {.function = HRNLIBSSH2_AGENT_DISCONNECT, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_AGENT_FREE}, + {.function = HRNLIBSSH2_SESSION_DISCONNECT_EX, .param = "[11,\"pgBackRest instance shutdown\",\"\"]", .resultInt = 0}, + {.function = HRNLIBSSH2_SESSION_FREE, .resultInt = 0}, + {.function = NULL} + }); + + storageTest = NULL; + + TEST_ASSIGN( + storageTest, + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + "new storage (defaults)"); + + memContextFree(objMemContext((StorageSftp *)storageDriver(storageTest))); +#else + hrnLibSsh2ScriptSet((HrnLibSsh2 []) + { + {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, + {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, + {.function = HRNLIBSSH2_HOSTKEY_HASH, .param = "[2]", .resultZ = "12345678909876543210"}, + {.function = HRNLIBSSH2_AGENT_INIT}, + {.function = NULL} + }); + + TEST_ERROR( + storageSftpNewP( + cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), + cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), + cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, + .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), + .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), + .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), + .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), + .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx)), + .identityAgent = cfgOptionIdxStrNull(cfgOptRepoSftpIdentityAgent, repoIdx), + .useSshAgent = cfgOptionIdxBool(cfgOptRepoSftpUseSshAgent, repoIdx)), + ServiceError, + "libssh2 version " LIBSSH2_VERSION " does not support ssh-agent identity path, requires version 1.9 or greater"); +#endif + // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("known host init failure"); @@ -318,7 +896,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -362,7 +940,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -392,7 +970,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -423,7 +1001,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -452,7 +1030,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -482,6 +1060,7 @@ testRun(void) {.function = NULL} }); + // Load configuration argList = strLstNew(); hrnCfgArgRawZ(argList, cfgOptStanza, "test"); hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); @@ -498,7 +1077,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -525,6 +1104,7 @@ testRun(void) {.function = NULL} }); + // Load configuration argList = strLstNew(); hrnCfgArgRawZ(argList, cfgOptStanza, "test"); hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); @@ -542,7 +1122,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -551,45 +1131,6 @@ testRun(void) .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx))), ServiceError, "known hosts failure: 'localhost' unknown failure [5]: check type [strict]"); - // ------------------------------------------------------------------------------------------------------------------------- - TEST_TITLE("public key from file auth failure, no public key"); - - hrnLibSsh2ScriptSet((HrnLibSsh2 []) - { - {.function = HRNLIBSSH2_INIT, .param = "[0]", .resultInt = LIBSSH2_ERROR_NONE}, - {.function = HRNLIBSSH2_SESSION_INIT_EX, .param = "[null,null,null,null]"}, - {.function = HRNLIBSSH2_SESSION_HANDSHAKE, .param = HANDSHAKE_PARAM, .resultInt = LIBSSH2_ERROR_NONE}, - {.function = HRNLIBSSH2_KNOWNHOST_INIT}, - {.function = HRNLIBSSH2_KNOWNHOST_READFILE, .param = "[\"" KNOWNHOSTS_FILE_CSTR "\",1]", .resultInt = 5}, - {.function = HRNLIBSSH2_SESSION_HOSTKEY, .len = 20, .type = LIBSSH2_HOSTKEY_TYPE_RSA, .resultZ = HOSTKEY}, - {.function = HRNLIBSSH2_KNOWNHOST_CHECKP, .param = "[\"localhost\",22,\"" HOSTKEY "\",20,65537]", - .resultInt = LIBSSH2_KNOWNHOST_CHECK_MATCH}, - {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, - .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",null,\"" KEYPRIV_CSTR "\",null]", .resultInt = -16}, - {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = LIBSSH2_FX_OK}, - {.function = NULL} - }); - - TEST_ERROR( - storageSftpNewP( - cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), - cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), - cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, - .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), - .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), - .hostFingerprint = cfgOptionIdxStrNull(cfgOptRepoSftpHostFingerprint, repoIdx), - .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), - .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx))), - ServiceError, - "public key authentication failed: libssh2 error [-16]\n" - "HINT: libssh2 compiled against non-openssl libraries requires --repo-sftp-private-key-file and" - " --repo-sftp-public-key-file to be provided\n" - "HINT: libssh2 versions before 1.9.0 expect a PEM format keypair, try ssh-keygen -m PEM -t rsa -P \"\" to generate the" - " keypair"); - TEST_RESULT_BOOL( - unsetenv("PGBACKREST_REPO1_SFTP_PRIVATE_KEY_PASSPHRASE"), 0, "unset PGBACKREST_REPO1_SFTP_PRIVATE_KEY_PASSPHRASE"); - // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("public key from file LIBSSH2_ERROR_EAGAIN, failure"); @@ -607,6 +1148,7 @@ testRun(void) .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", .resultInt = LIBSSH2_ERROR_EAGAIN}, {.function = HRNLIBSSH2_SESSION_BLOCK_DIRECTIONS, .resultInt = SSH2_BLOCK_READING_WRITING}, + {.function = HRNLIBSSH2_SFTP_LAST_ERROR, .resultUInt = LIBSSH2_FX_OK}, {.function = NULL} }); @@ -628,7 +1170,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -636,7 +1178,7 @@ testRun(void) .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx))), ServiceError, - "timeout during public key authentication"); + "ssh authentication failed: libssh2 error [-37]"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("sftp session init failure ssh2 error"); @@ -662,11 +1204,26 @@ testRun(void) {.function = NULL} }); + // Load configuration + argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + hrnCfgArgRawZ(argList, cfgOptRepo, "1"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostUser, TEST_USER); + hrnCfgArgRawZ(argList, cfgOptRepoType, "sftp"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHost, "localhost"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpHostKeyHashType, "sha1"); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPrivateKeyFile, KEYPRIV_CSTR); + hrnCfgArgRawZ(argList, cfgOptRepoSftpPublicKeyFile, KEYPUB_CSTR); + hrnCfgArgRawZ(argList, cfgOptRepoSftpKnownHost, KNOWNHOSTS_FILE_CSTR); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + TEST_ERROR( storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -704,7 +1261,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -745,7 +1302,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -764,14 +1321,14 @@ testRun(void) HRNLIBSSH2_MACRO_SHUTDOWN() }); - Storage *storageTest = NULL; + storageTest = NULL; TEST_ASSIGN( storageTest, storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -820,7 +1377,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -879,7 +1436,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -945,7 +1502,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -999,7 +1556,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1052,7 +1609,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1128,7 +1685,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1144,7 +1701,8 @@ testRun(void) "provided [-16]\n" "P00 WARN: host 'localhost' not found in known hosts files, attempting to add host to " "'/home/" TEST_USER "/.ssh/known_hosts'\n" - "P00 WARN: pgBackRest added new host 'localhost' to '/home/" TEST_USER "/.ssh/known_hosts'"); + "P00 WARN: pgBackRest added new host 'localhost' to '/home/" TEST_USER "/.ssh/known_hosts'\n" + "P00 DETAIL: public key authentication with username " TEST_USER " and key /home/" TEST_USER "/.ssh/id_rsa succeeded"); harnessLogLevelReset(); @@ -1191,7 +1749,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1248,7 +1806,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1306,7 +1864,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1364,7 +1922,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1422,7 +1980,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1479,7 +2037,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1531,7 +2089,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1585,7 +2143,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1634,7 +2192,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1663,7 +2221,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1688,7 +2246,7 @@ testRun(void) {.function = HRNLIBSSH2_KNOWNHOST_CHECKP, .param = "[\"localhost\",22,\"" HOSTKEY "\",20,65537]", .resultInt = LIBSSH2_KNOWNHOST_CHECK_MATCH}, {.function = HRNLIBSSH2_USERAUTH_PUBLICKEY_FROMFILE_EX, - .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",null,\"" KEYPRIV_CSTR "\",null]", .resultInt = 0}, + .param = "[\"" TEST_USER "\"," TEST_USER_LEN ",\"" KEYPUB_CSTR "\",\"" KEYPRIV_CSTR "\",null]", .resultInt = 0}, {.function = HRNLIBSSH2_SFTP_INIT}, HRNLIBSSH2_MACRO_SHUTDOWN() }); @@ -1698,7 +2256,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1764,7 +2322,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1812,7 +2370,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1863,7 +2421,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1916,7 +2474,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -1964,7 +2522,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = 0600, .modePath = 0700, .write = true, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2024,7 +2582,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2032,11 +2590,7 @@ testRun(void) .hostKeyCheckType = cfgOptionIdxStrId(cfgOptRepoSftpHostKeyCheckType, repoIdx), .knownHosts = strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpKnownHost, repoIdx))), ServiceError, - "public key authentication failed: libssh2 error [-16]\n" - "HINT: libssh2 compiled against non-openssl libraries requires --repo-sftp-private-key-file and" - " --repo-sftp-public-key-file to be provided\n" - "HINT: libssh2 versions before 1.9.0 expect a PEM format keypair, try ssh-keygen -m PEM -t rsa -P \"\" to generate the" - " keypair"); + "ssh authentication failed: libssh2 error [-16]"); TEST_RESULT_BOOL( unsetenv("PGBACKREST_REPO1_SFTP_PRIVATE_KEY_PASSPHRASE"), 0, "unset PGBACKREST_REPO1_SFTP_PRIVATE_KEY_PASSPHRASE"); @@ -2130,7 +2684,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2217,7 +2771,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2244,7 +2798,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2286,7 +2840,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2310,7 +2864,7 @@ testRun(void) Storage *storageRootNoPath = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2432,7 +2986,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2752,7 +3306,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -2894,7 +3448,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3010,7 +3564,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3170,7 +3724,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3330,7 +3884,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3500,7 +4054,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3641,7 +4195,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3712,7 +4266,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3845,7 +4399,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3919,7 +4473,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -3965,7 +4519,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4108,7 +4662,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4181,7 +4735,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4373,7 +4927,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4496,7 +5050,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4529,7 +5083,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4562,7 +5116,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4621,7 +5175,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4678,7 +5232,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4712,7 +5266,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4740,7 +5294,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4773,7 +5327,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4807,7 +5361,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4840,7 +5394,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4872,7 +5426,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4904,7 +5458,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4955,7 +5509,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -4991,7 +5545,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5026,7 +5580,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5066,7 +5620,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5102,7 +5656,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5140,7 +5694,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5183,7 +5737,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5225,7 +5779,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5266,7 +5820,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5308,7 +5862,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5349,7 +5903,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5385,7 +5939,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5420,7 +5974,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5461,7 +6015,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5500,7 +6054,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5538,7 +6092,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5581,7 +6135,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5616,7 +6170,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5653,7 +6207,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5697,7 +6251,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5741,7 +6295,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5778,7 +6332,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5813,7 +6367,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5844,7 +6398,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5889,7 +6443,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5917,7 +6471,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5946,7 +6500,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -5980,7 +6534,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6012,7 +6566,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6044,7 +6598,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6080,7 +6634,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6110,7 +6664,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6139,7 +6693,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6171,7 +6725,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6205,7 +6759,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6236,7 +6790,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6288,7 +6842,7 @@ testRun(void) Storage *storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6316,7 +6870,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6346,7 +6900,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6375,7 +6929,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6404,7 +6958,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6435,7 +6989,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6477,7 +7031,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6513,7 +7067,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6546,7 +7100,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6601,7 +7155,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6678,7 +7232,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6781,7 +7335,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6856,7 +7410,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -6930,7 +7484,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7017,7 +7571,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7116,7 +7670,7 @@ testRun(void) storageTest = storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7438,7 +7992,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7469,7 +8023,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7501,7 +8055,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7537,7 +8091,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7573,7 +8127,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7607,7 +8161,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7636,7 +8190,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7665,7 +8219,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7695,7 +8249,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7726,7 +8280,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7757,7 +8311,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx), @@ -7789,7 +8343,7 @@ testRun(void) storageSftpNewP( cfgOptionIdxStr(cfgOptRepoPath, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHost, repoIdx), cfgOptionIdxUInt(cfgOptRepoSftpHostPort, repoIdx), cfgOptionIdxStr(cfgOptRepoSftpHostUser, repoIdx), - cfgOptionUInt64(cfgOptIoTimeout), cfgOptionIdxStr(cfgOptRepoSftpPrivateKeyFile, repoIdx), + cfgOptionUInt64(cfgOptIoTimeout), strLstNewVarLst(cfgOptionIdxLst(cfgOptRepoSftpPrivateKeyFile, repoIdx)), cfgOptionIdxStrId(cfgOptRepoSftpHostKeyHashType, repoIdx), .modeFile = STORAGE_MODE_FILE_DEFAULT, .modePath = STORAGE_MODE_PATH_DEFAULT, .keyPub = cfgOptionIdxStrNull(cfgOptRepoSftpPublicKeyFile, repoIdx), .keyPassphrase = cfgOptionIdxStrNull(cfgOptRepoSftpPrivateKeyPassphrase, repoIdx),