mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-12 03:00:26 +09:00
Compare commits
4 Commits
00f1d6fac2
...
358553e976
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
358553e976 | ||
|
|
07d099f652 | ||
|
|
f3d70e54e9 | ||
|
|
74d1bf51b5 |
@@ -21,7 +21,7 @@ clients must be made or how a client should react.
|
|||||||
#include "examples_common.h"
|
#include "examples_common.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
ssh_session connect_ssh(const char *host, const char *user, int verbosity)
|
ssh_session connect_ssh(const char *host, const char *port, const char *user, int verbosity)
|
||||||
{
|
{
|
||||||
ssh_session session = NULL;
|
ssh_session session = NULL;
|
||||||
int auth = 0;
|
int auth = 0;
|
||||||
@@ -38,6 +38,13 @@ ssh_session connect_ssh(const char *host, const char *user, int verbosity)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (port != NULL) {
|
||||||
|
if (ssh_options_set(session, SSH_OPTIONS_PORT_STR, port) < 0) {
|
||||||
|
ssh_free(session);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ clients must be made or how a client should react.
|
|||||||
int authenticate_console(ssh_session session);
|
int authenticate_console(ssh_session session);
|
||||||
int authenticate_kbdint(ssh_session session, const char *password);
|
int authenticate_kbdint(ssh_session session, const char *password);
|
||||||
int verify_knownhost(ssh_session session);
|
int verify_knownhost(ssh_session session);
|
||||||
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
|
ssh_session connect_ssh(const char *hostname, const char *port, const char *user, int verbosity);
|
||||||
|
|
||||||
#endif /* EXAMPLES_COMMON_H_ */
|
#endif /* EXAMPLES_COMMON_H_ */
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ int main(void) {
|
|||||||
int rbytes, wbytes, total = 0;
|
int rbytes, wbytes, total = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
session = connect_ssh("localhost", NULL, 0);
|
session = connect_ssh("localhost", NULL, NULL, 0);
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ static char **sources = NULL;
|
|||||||
static int nsources;
|
static int nsources;
|
||||||
static char *destination = NULL;
|
static char *destination = NULL;
|
||||||
static int verbosity = 0;
|
static int verbosity = 0;
|
||||||
|
static char *port = NULL;
|
||||||
|
|
||||||
struct location {
|
struct location {
|
||||||
int is_ssh;
|
int is_ssh;
|
||||||
@@ -49,9 +50,10 @@ enum {
|
|||||||
static void usage(const char *argv0) {
|
static void usage(const char *argv0) {
|
||||||
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
|
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||||
" [[user@]host2:]destination\n"
|
" [[user@]host2:]destination\n"
|
||||||
"sample scp client - libssh-%s\n",
|
"sample scp client - libssh-%s\n"
|
||||||
// "Options :\n",
|
"Options :\n"
|
||||||
// " -r : use RSA to verify host public key\n",
|
" -P : use port to connect to remote host\n"
|
||||||
|
" -v : increase verbosity of libssh. Can be used multiple times\n",
|
||||||
argv0,
|
argv0,
|
||||||
ssh_version(0));
|
ssh_version(0));
|
||||||
exit(0);
|
exit(0);
|
||||||
@@ -60,11 +62,14 @@ static void usage(const char *argv0) {
|
|||||||
static int opts(int argc, char **argv) {
|
static int opts(int argc, char **argv) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
while((i = getopt(argc, argv, "v")) != -1) {
|
while((i = getopt(argc, argv, "P:v")) != -1) {
|
||||||
switch(i) {
|
switch(i) {
|
||||||
case 'v':
|
case 'v':
|
||||||
verbosity++;
|
verbosity++;
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
port = optarg;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown option %c\n", optopt);
|
fprintf(stderr, "unknown option %c\n", optopt);
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
@@ -183,7 +188,7 @@ static void close_location(struct location *loc) {
|
|||||||
|
|
||||||
static int open_location(struct location *loc, int flag) {
|
static int open_location(struct location *loc, int flag) {
|
||||||
if (loc->is_ssh && flag == WRITE) {
|
if (loc->is_ssh && flag == WRITE) {
|
||||||
loc->session = connect_ssh(loc->host, loc->user, verbosity);
|
loc->session = connect_ssh(loc->host, port, loc->user, verbosity);
|
||||||
if (!loc->session) {
|
if (!loc->session) {
|
||||||
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -209,7 +214,7 @@ static int open_location(struct location *loc, int flag) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (loc->is_ssh && flag == READ) {
|
} else if (loc->is_ssh && flag == READ) {
|
||||||
loc->session = connect_ssh(loc->host, loc->user, verbosity);
|
loc->session = connect_ssh(loc->host, port, loc->user, verbosity);
|
||||||
if (!loc->session) {
|
if (!loc->session) {
|
||||||
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ int main(int argc, char **argv)
|
|||||||
ssh_session session = NULL;
|
ssh_session session = NULL;
|
||||||
if (opts(argc, argv) < 0)
|
if (opts(argc, argv) < 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
session = connect_ssh(host, NULL, verbosity);
|
session = connect_ssh(host, NULL, NULL, verbosity);
|
||||||
if (session == NULL)
|
if (session == NULL)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
create_files(session);
|
create_files(session);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ int main(void)
|
|||||||
int rc;
|
int rc;
|
||||||
uint64_t total = 0;
|
uint64_t total = 0;
|
||||||
uint64_t lastshown = 4096;
|
uint64_t lastshown = 4096;
|
||||||
session = connect_ssh("localhost", NULL, 0);
|
session = connect_ssh("localhost", NULL, NULL, 0);
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -844,6 +844,7 @@ LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
|
|||||||
do { if ((x) != NULL) { ssh_string_free(x); x = NULL; } } while(0)
|
do { if ((x) != NULL) { ssh_string_free(x); x = NULL; } } while(0)
|
||||||
LIBSSH_API void ssh_string_free(ssh_string str);
|
LIBSSH_API void ssh_string_free(ssh_string str);
|
||||||
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
|
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
|
||||||
|
LIBSSH_API ssh_string ssh_string_from_data(const void *data, size_t len);
|
||||||
LIBSSH_API size_t ssh_string_len(ssh_string str);
|
LIBSSH_API size_t ssh_string_len(ssh_string str);
|
||||||
LIBSSH_API ssh_string ssh_string_new(size_t size);
|
LIBSSH_API ssh_string ssh_string_new(size_t size);
|
||||||
LIBSSH_API const char *ssh_string_get_char(ssh_string str);
|
LIBSSH_API const char *ssh_string_get_char(ssh_string str);
|
||||||
|
|||||||
@@ -89,6 +89,9 @@ enum ssh_pending_call_e {
|
|||||||
#define SSH_SESSION_FLAG_KEX_STRICT 0x0010
|
#define SSH_SESSION_FLAG_KEX_STRICT 0x0010
|
||||||
/* Unexpected packets have been sent while the session was still unencrypted */
|
/* Unexpected packets have been sent while the session was still unencrypted */
|
||||||
#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020
|
#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020
|
||||||
|
/* The scp on server can not handle quoted paths. Skip the mitigation for
|
||||||
|
* CVE-2019-14889 when using scp */
|
||||||
|
#define SSH_SESSION_FLAG_SCP_QUOTING_BROKEN 0x0040
|
||||||
|
|
||||||
/* codes to use with ssh_handle_packets*() */
|
/* codes to use with ssh_handle_packets*() */
|
||||||
/* Infinite timeout */
|
/* Infinite timeout */
|
||||||
|
|||||||
@@ -492,5 +492,6 @@ LIBSSH_AFTER_4_10_0
|
|||||||
sshsig_sign;
|
sshsig_sign;
|
||||||
sshsig_verify;
|
sshsig_verify;
|
||||||
ssh_string_cmp;
|
ssh_string_cmp;
|
||||||
|
ssh_string_from_data;
|
||||||
} LIBSSH_4_10_0;
|
} LIBSSH_4_10_0;
|
||||||
|
|
||||||
|
|||||||
@@ -1376,6 +1376,7 @@ int ssh_analyze_banner(ssh_session session, int server)
|
|||||||
{
|
{
|
||||||
const char *banner = NULL;
|
const char *banner = NULL;
|
||||||
const char *openssh = NULL;
|
const char *openssh = NULL;
|
||||||
|
const char *ios = NULL;
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
banner = session->clientbanner;
|
banner = session->clientbanner;
|
||||||
@@ -1465,6 +1466,11 @@ int ssh_analyze_banner(ssh_session session, int server)
|
|||||||
major, minor, session->openssh);
|
major, minor, session->openssh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Cisco devices have odd scp implementation which breaks */
|
||||||
|
ios = strstr(banner, "Cisco");
|
||||||
|
if (ios != NULL) {
|
||||||
|
session->flags |= SSH_SESSION_FLAG_SCP_QUOTING_BROKEN;
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
12
src/scp.c
12
src/scp.c
@@ -30,6 +30,7 @@
|
|||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/scp.h"
|
#include "libssh/scp.h"
|
||||||
#include "libssh/misc.h"
|
#include "libssh/misc.h"
|
||||||
|
#include "libssh/session.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup libssh_scp The SSH scp functions
|
* @defgroup libssh_scp The SSH scp functions
|
||||||
@@ -197,6 +198,17 @@ int ssh_scp_init(ssh_scp scp)
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Some servers do not handle the quoting well. Pass in the raw file
|
||||||
|
* location */
|
||||||
|
if (scp->session->flags & SSH_SESSION_FLAG_SCP_QUOTING_BROKEN) {
|
||||||
|
free(quoted_location);
|
||||||
|
quoted_location = strdup(scp->location);
|
||||||
|
if (quoted_location == NULL) {
|
||||||
|
ssh_set_error_oom(scp->session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (scp->mode == SSH_SCP_WRITE) {
|
if (scp->mode == SSH_SCP_WRITE) {
|
||||||
snprintf(execbuffer, sizeof(execbuffer), "scp -t %s %s",
|
snprintf(execbuffer, sizeof(execbuffer), "scp -t %s %s",
|
||||||
scp->recursive ? "-r" : "", quoted_location);
|
scp->recursive ? "-r" : "", quoted_location);
|
||||||
|
|||||||
39
src/string.c
39
src/string.c
@@ -128,6 +128,45 @@ struct ssh_string_struct *ssh_string_from_char(const char *what)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a ssh string from an arbitrary data buffer.
|
||||||
|
*
|
||||||
|
* Allocates a new SSH string of length `len` and copies the provided data
|
||||||
|
* into it. If len is 0, returns an empty SSH string. When len > 0, data
|
||||||
|
* must not be NULL.
|
||||||
|
*
|
||||||
|
* @param[in] data Pointer to the data buffer to copy from. May be NULL
|
||||||
|
* only when len == 0.
|
||||||
|
* @param[in] len Length of the data buffer to copy.
|
||||||
|
*
|
||||||
|
* @return The newly allocated string, NULL on error.
|
||||||
|
*/
|
||||||
|
struct ssh_string_struct *ssh_string_from_data(const void *data, size_t len)
|
||||||
|
{
|
||||||
|
struct ssh_string_struct *s = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (len > 0 && data == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = ssh_string_new(len);
|
||||||
|
if (s == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
rc = ssh_string_fill(s, data, len);
|
||||||
|
if (rc != 0) {
|
||||||
|
ssh_string_free(s);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the size of a SSH string.
|
* @brief Return the size of a SSH string.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ int main(void) {
|
|||||||
char buffer[1024*1024];
|
char buffer[1024*1024];
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
session = connect_ssh("localhost", NULL, 0);
|
session = connect_ssh("localhost", NULL, NULL, 0);
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,33 @@ static void torture_ssh_string_from_char(void **state)
|
|||||||
assert_int_equal(errno, EINVAL);
|
assert_int_equal(errno, EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_ssh_string_from_data(void **state)
|
||||||
|
{
|
||||||
|
ssh_string s;
|
||||||
|
const unsigned char raw[] = {0x00, 0x01, 0x00, 0x42, 0xFF};
|
||||||
|
|
||||||
|
(void)state;
|
||||||
|
|
||||||
|
/* Basic: copy arbitrary binary data (with embedded NUL) */
|
||||||
|
s = ssh_string_from_data(raw, sizeof(raw));
|
||||||
|
assert_non_null(s);
|
||||||
|
assert_int_equal(ssh_string_len(s), sizeof(raw));
|
||||||
|
assert_memory_equal(ssh_string_data(s), raw, sizeof(raw));
|
||||||
|
ssh_string_free(s);
|
||||||
|
|
||||||
|
/* Empty: len == 0 with NULL data returns empty string */
|
||||||
|
s = ssh_string_from_data(NULL, 0);
|
||||||
|
assert_non_null(s);
|
||||||
|
assert_int_equal(ssh_string_len(s), 0);
|
||||||
|
ssh_string_free(s);
|
||||||
|
|
||||||
|
/* Invalid: len > 0 with NULL data fails and sets errno */
|
||||||
|
errno = 0;
|
||||||
|
s = ssh_string_from_data(NULL, 42);
|
||||||
|
assert_null(s);
|
||||||
|
assert_int_equal(errno, EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
static void torture_ssh_string_fill(void **state)
|
static void torture_ssh_string_fill(void **state)
|
||||||
{
|
{
|
||||||
struct ssh_string_struct *str = NULL;
|
struct ssh_string_struct *str = NULL;
|
||||||
@@ -380,6 +407,7 @@ int torture_run_tests(void)
|
|||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
cmocka_unit_test(torture_ssh_string_new),
|
cmocka_unit_test(torture_ssh_string_new),
|
||||||
cmocka_unit_test(torture_ssh_string_from_char),
|
cmocka_unit_test(torture_ssh_string_from_char),
|
||||||
|
cmocka_unit_test(torture_ssh_string_from_data),
|
||||||
cmocka_unit_test(torture_ssh_string_fill),
|
cmocka_unit_test(torture_ssh_string_fill),
|
||||||
cmocka_unit_test(torture_ssh_string_to_char),
|
cmocka_unit_test(torture_ssh_string_to_char),
|
||||||
cmocka_unit_test(torture_ssh_string_copy),
|
cmocka_unit_test(torture_ssh_string_copy),
|
||||||
|
|||||||
Reference in New Issue
Block a user