mirror of
https://github.com/upa/mscp.git
synced 2026-03-07 08:07:31 +08:00
add -o SSH_OPTION option
This commit is contained in:
@@ -47,7 +47,10 @@ mscp \- copy files over multiple SSH connections
|
|||||||
.BI \-P \ PORT\c
|
.BI \-P \ PORT\c
|
||||||
]
|
]
|
||||||
[\c
|
[\c
|
||||||
.BI \-F \ CONFIG\c
|
.BI \-F \ SSH_CONFIG\c
|
||||||
|
]
|
||||||
|
[\c
|
||||||
|
.BI \-o \ SSH_OPTION\c
|
||||||
]
|
]
|
||||||
[\c
|
[\c
|
||||||
.BI \-i \ IDENTITY\c
|
.BI \-i \ IDENTITY\c
|
||||||
@@ -247,12 +250,19 @@ Specifies the port number to connect to on the remote machine as with
|
|||||||
ssh(1) and scp(1).
|
ssh(1) and scp(1).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-F \fICONFIG\fR
|
.B \-F \fISSH_CONFIG\fR
|
||||||
Specifies an alternative per-user ssh configuration file. Note that
|
Specifies an alternative per-user ssh configuration file. Note that
|
||||||
acceptable options in the configuration file are what
|
acceptable options in the configuration file are what
|
||||||
.I libssh
|
.I libssh
|
||||||
supports.
|
supports.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B \-o \fISSH_OPTION\fR
|
||||||
|
Specifies ssh options in the format used in ssh_config. Note that
|
||||||
|
acceptable options are what
|
||||||
|
.I libssh
|
||||||
|
supports.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-i \fIIDENTITY\fR
|
.B \-i \fIIDENTITY\fR
|
||||||
Specifies the identity file for public key authentication.
|
Specifies the identity file for public key authentication.
|
||||||
|
|||||||
14
doc/mscp.rst
14
doc/mscp.rst
@@ -2,7 +2,7 @@
|
|||||||
MSCP
|
MSCP
|
||||||
====
|
====
|
||||||
|
|
||||||
:Date: v0.1.5-10-g00fa2c7
|
:Date: v0.1.5-13-gf2f0dab
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
====
|
====
|
||||||
@@ -17,9 +17,9 @@ SYNOPSIS
|
|||||||
*CHECKPOINT* ] [ **-R** *CHECKPOINT* ] [ **-s** *MIN_CHUNK_SIZE* ] [
|
*CHECKPOINT* ] [ **-R** *CHECKPOINT* ] [ **-s** *MIN_CHUNK_SIZE* ] [
|
||||||
**-S** *MAX_CHUNK_SIZE* ] [ **-a** *NR_AHEAD* ] [ **-b** *BUF_SIZE* ] [
|
**-S** *MAX_CHUNK_SIZE* ] [ **-a** *NR_AHEAD* ] [ **-b** *BUF_SIZE* ] [
|
||||||
**-L** *LIMIT_BITRATE* ] [ **-l** *LOGIN_NAME* ] [ **-P** *PORT* ] [
|
**-L** *LIMIT_BITRATE* ] [ **-l** *LOGIN_NAME* ] [ **-P** *PORT* ] [
|
||||||
**-F** *CONFIG* ] [ **-i** *IDENTITY* ] [ **-c** *CIPHER* ] [ **-M**
|
**-F** *SSH_CONFIG* ] [ **-o** *SSH_OPTION* ] [ **-i** *IDENTITY* ] [
|
||||||
*HMAC* ] [ **-C** *COMPRESS* ] [ **-g** *CONGESTION* ] *source ...
|
**-c** *CIPHER* ] [ **-M** *HMAC* ] [ **-C** *COMPRESS* ] [ **-g**
|
||||||
target*
|
*CONGESTION* ] *source ... target*
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
===========
|
===========
|
||||||
@@ -144,11 +144,15 @@ OPTIONS
|
|||||||
Specifies the port number to connect to on the remote machine as with
|
Specifies the port number to connect to on the remote machine as with
|
||||||
ssh(1) and scp(1).
|
ssh(1) and scp(1).
|
||||||
|
|
||||||
**-F CONFIG**
|
**-F SSH_CONFIG**
|
||||||
Specifies an alternative per-user ssh configuration file. Note that
|
Specifies an alternative per-user ssh configuration file. Note that
|
||||||
acceptable options in the configuration file are what *libssh*
|
acceptable options in the configuration file are what *libssh*
|
||||||
supports.
|
supports.
|
||||||
|
|
||||||
|
**-o SSH_OPTION**
|
||||||
|
Specifies ssh options in the format used in ssh_config. Note that
|
||||||
|
acceptable options are what *libssh* supports.
|
||||||
|
|
||||||
**-i IDENTITY**
|
**-i IDENTITY**
|
||||||
Specifies the identity file for public key authentication.
|
Specifies the identity file for public key authentication.
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ struct mscp_ssh_opts {
|
|||||||
char *port; /** ssh port */
|
char *port; /** ssh port */
|
||||||
int ai_family; /** address family */
|
int ai_family; /** address family */
|
||||||
char *config; /** path to ssh_config, default ~/.ssh/config*/
|
char *config; /** path to ssh_config, default ~/.ssh/config*/
|
||||||
|
char **options; /** array of ssh_config options, terminated by NULL */
|
||||||
char *identity; /** path to private key */
|
char *identity; /** path to private key */
|
||||||
char *cipher; /** cipher spec */
|
char *cipher; /** cipher spec */
|
||||||
char *hmac; /** hmacp spec */
|
char *hmac; /** hmacp spec */
|
||||||
|
|||||||
21
src/main.c
21
src/main.c
@@ -28,8 +28,9 @@ void usage(bool print_help)
|
|||||||
" [-u max_startups] [-I interval] [-W checkpoint] [-R checkpoint]\n"
|
" [-u max_startups] [-I interval] [-W checkpoint] [-R checkpoint]\n"
|
||||||
" [-s min_chunk_sz] [-S max_chunk_sz] [-a nr_ahead]\n"
|
" [-s min_chunk_sz] [-S max_chunk_sz] [-a nr_ahead]\n"
|
||||||
" [-b buf_sz] [-L limit_bitrate]\n"
|
" [-b buf_sz] [-L limit_bitrate]\n"
|
||||||
" [-l login_name] [-P port] [-F ssh_config] [-i identity_file]\n"
|
" [-l login_name] [-P port] [-F ssh_config] [-o ssh_option]\n"
|
||||||
" [-c cipher_spec] [-M hmac_spec] [-C compress] [-g congestion]\n"
|
" [-i identity_file] [-c cipher_spec] [-M hmac_spec]\n"
|
||||||
|
" [-C compress] [-g congestion]\n"
|
||||||
" source ... target\n"
|
" source ... target\n"
|
||||||
"\n");
|
"\n");
|
||||||
|
|
||||||
@@ -60,7 +61,8 @@ void usage(bool print_help)
|
|||||||
"\n"
|
"\n"
|
||||||
" -l LOGIN_NAME login name\n"
|
" -l LOGIN_NAME login name\n"
|
||||||
" -P PORT port number\n"
|
" -P PORT port number\n"
|
||||||
" -F CONFIG path to user ssh config (default ~/.ssh/config)\n"
|
" -F SSH_CONFIG path to user ssh config (default ~/.ssh/config)\n"
|
||||||
|
" -o SSH_OPTION ssh_config option\n"
|
||||||
" -i IDENTITY identity file for public key authentication\n"
|
" -i IDENTITY identity file for public key authentication\n"
|
||||||
" -c CIPHER cipher spec\n"
|
" -c CIPHER cipher spec\n"
|
||||||
" -M HMAC hmac spec\n"
|
" -M HMAC hmac spec\n"
|
||||||
@@ -267,6 +269,7 @@ int main(int argc, char **argv)
|
|||||||
int direction = 0;
|
int direction = 0;
|
||||||
char *remote = NULL, *checkpoint_save = NULL, *checkpoint_load = NULL;
|
char *remote = NULL, *checkpoint_save = NULL, *checkpoint_load = NULL;
|
||||||
bool dryrun = false, resume = false;
|
bool dryrun = false, resume = false;
|
||||||
|
int nr_options = 0;
|
||||||
size_t factor = 1;
|
size_t factor = 1;
|
||||||
char *unit;
|
char *unit;
|
||||||
|
|
||||||
@@ -274,7 +277,7 @@ int main(int argc, char **argv)
|
|||||||
memset(&o, 0, sizeof(o));
|
memset(&o, 0, sizeof(o));
|
||||||
o.severity = MSCP_SEVERITY_WARN;
|
o.severity = MSCP_SEVERITY_WARN;
|
||||||
|
|
||||||
#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:46vqDrl:P:i:F:c:M:C:g:pdNh"
|
#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:46vqDrl:P:i:F:o:c:M:C:g:pdNh"
|
||||||
while ((ch = getopt(argc, argv, mscpopts)) != -1) {
|
while ((ch = getopt(argc, argv, mscpopts)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'n':
|
case 'n':
|
||||||
@@ -359,6 +362,16 @@ int main(int argc, char **argv)
|
|||||||
case 'F':
|
case 'F':
|
||||||
s.config = optarg;
|
s.config = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'o':
|
||||||
|
nr_options++;
|
||||||
|
s.options = realloc(s.options, sizeof(char *) * (nr_options + 1));
|
||||||
|
if (!s.options) {
|
||||||
|
pr_err("realloc: %s", strerrno());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
s.options[nr_options - 1] = optarg;
|
||||||
|
s.options[nr_options] = NULL;
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
s.identity = optarg;
|
s.identity = optarg;
|
||||||
break;
|
break;
|
||||||
|
|||||||
16
src/ssh.c
16
src/ssh.c
@@ -4,12 +4,13 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "libssh/callbacks.h"
|
|
||||||
|
|
||||||
#include <ssh.h>
|
#include <ssh.h>
|
||||||
#include <mscp.h>
|
#include <mscp.h>
|
||||||
#include <strerrno.h>
|
#include <strerrno.h>
|
||||||
|
|
||||||
|
#include "libssh/callbacks.h"
|
||||||
|
#include "libssh/options.h"
|
||||||
|
|
||||||
static int ssh_verify_known_hosts(ssh_session session);
|
static int ssh_verify_known_hosts(ssh_session session);
|
||||||
static int ssh_authenticate_kbdint(ssh_session session);
|
static int ssh_authenticate_kbdint(ssh_session session);
|
||||||
|
|
||||||
@@ -87,6 +88,17 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->options) {
|
||||||
|
int n;
|
||||||
|
for (n = 0; opts->options[n]; n++) {
|
||||||
|
if (ssh_config_parse_string(ssh, opts->options[n]) != SSH_OK) {
|
||||||
|
priv_set_errv("failed to set ssh option %s: %s",
|
||||||
|
opts->options[n]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -496,6 +496,40 @@ def test_config_ng(mscp, src_prefix, dst_prefix):
|
|||||||
src.cleanup()
|
src.cleanup()
|
||||||
dst.cleanup()
|
dst.cleanup()
|
||||||
|
|
||||||
|
|
||||||
|
param_valid_option_ok = [
|
||||||
|
[ "-o", "Port=8022" ],
|
||||||
|
[ "-o", "Port=8022", "-o", "User=root" ],
|
||||||
|
[ "-o", "unknown-option-is-silently-ignored" ],
|
||||||
|
]
|
||||||
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
|
@pytest.mark.parametrize("option", param_valid_option_ok)
|
||||||
|
def test_inline_option_ok(mscp, src_prefix, dst_prefix, option):
|
||||||
|
""" change port number with -o option. it should be ok. """
|
||||||
|
src = File("src", size = 1024 * 1024).make()
|
||||||
|
dst = File("dst")
|
||||||
|
run2ok([mscp, "-vvv"] + option +
|
||||||
|
[src_prefix + src.path, dst_prefix + dst.path])
|
||||||
|
assert check_same_md5sum(src, dst)
|
||||||
|
src.cleanup()
|
||||||
|
dst.cleanup()
|
||||||
|
|
||||||
|
|
||||||
|
param_valid_option_ng = [
|
||||||
|
[ "-o", "Port=8023" ],
|
||||||
|
[ "-o", "User=invaliduser" ],
|
||||||
|
]
|
||||||
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
|
@pytest.mark.parametrize("option", param_valid_option_ng)
|
||||||
|
def test_inline_option_ng(mscp, src_prefix, dst_prefix, option):
|
||||||
|
""" change port number with -o option. it should be ng. """
|
||||||
|
src = File("src", size = 1024 * 1024).make()
|
||||||
|
dst = File("dst")
|
||||||
|
run2ng([mscp, "-vvv"] + option +
|
||||||
|
[src_prefix + src.path, dst_prefix + dst.path])
|
||||||
|
src.cleanup()
|
||||||
|
|
||||||
|
|
||||||
# username test assumes that this test runs inside a container, see Dockerfiles
|
# username test assumes that this test runs inside a container, see Dockerfiles
|
||||||
def test_specify_passphrase_via_env(mscp):
|
def test_specify_passphrase_via_env(mscp):
|
||||||
src = File(os.getcwd() + "/src", size = 1024).make()
|
src = File(os.getcwd() + "/src", size = 1024).make()
|
||||||
@@ -552,8 +586,8 @@ def test_10k_files(mscp, src_prefix, dst_prefix):
|
|||||||
|
|
||||||
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
|
||||||
def test_checkpoint_dump_and_resume(mscp, src_prefix, dst_prefix):
|
def test_checkpoint_dump_and_resume(mscp, src_prefix, dst_prefix):
|
||||||
src1 = File("src1", size = 512 * 1024 * 1024).make()
|
src1 = File("src1", size = 64 * 1024 * 1024).make()
|
||||||
src2 = File("src2", size = 512 * 1024 * 1024).make()
|
src2 = File("src2", size = 64 * 1024 * 1024).make()
|
||||||
dst1 = File("dst/src1")
|
dst1 = File("dst/src1")
|
||||||
dst2 = File("dst/src2")
|
dst2 = File("dst/src2")
|
||||||
run2ok([mscp, "-vvv", "-W", "checkpoint", "-D",
|
run2ok([mscp, "-vvv", "-W", "checkpoint", "-D",
|
||||||
|
|||||||
Reference in New Issue
Block a user