mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-07-31 00:03:07 +03:00
tests: Improve sftpserver test coverage
Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org> Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
This commit is contained in:
@ -22,6 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "libssh/sftp.h"
|
||||||
|
|
||||||
#define LIBSSH_STATIC
|
#define LIBSSH_STATIC
|
||||||
|
|
||||||
@ -263,6 +264,59 @@ static int session_setup(void **state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int session_setup_sftp(void **state)
|
||||||
|
{
|
||||||
|
struct test_server_st *tss = *state;
|
||||||
|
struct torture_state *s;
|
||||||
|
struct torture_sftp *tsftp;
|
||||||
|
ssh_session session;
|
||||||
|
sftp_session sftp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert_non_null(tss);
|
||||||
|
|
||||||
|
rc = session_setup(state);
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
|
||||||
|
s = tss->state;
|
||||||
|
assert_non_null(s);
|
||||||
|
|
||||||
|
session = s->ssh.session;
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
rc = ssh_options_set(session, SSH_OPTIONS_USER, SSHD_DEFAULT_USER);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
|
rc = ssh_connect(session);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
|
rc = ssh_userauth_none(session, NULL);
|
||||||
|
/* This request should return a SSH_REQUEST_DENIED error */
|
||||||
|
if (rc == SSH_AUTH_ERROR) {
|
||||||
|
assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
|
||||||
|
}
|
||||||
|
rc = ssh_userauth_list(session, NULL);
|
||||||
|
assert_true(rc & SSH_AUTH_METHOD_PASSWORD);
|
||||||
|
|
||||||
|
rc = ssh_userauth_password(session, NULL, SSHD_DEFAULT_PASSWORD);
|
||||||
|
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||||
|
|
||||||
|
ssh_get_issue_banner(session);
|
||||||
|
|
||||||
|
/* init sftp session */
|
||||||
|
tsftp = s->ssh.tsftp;
|
||||||
|
|
||||||
|
printf("in establish before sftp_new\n");
|
||||||
|
sftp = sftp_new(session);
|
||||||
|
assert_non_null(sftp);
|
||||||
|
tsftp->sftp = sftp;
|
||||||
|
|
||||||
|
rc = sftp_init(sftp);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int session_teardown(void **state)
|
static int session_teardown(void **state)
|
||||||
{
|
{
|
||||||
struct test_server_st *tss = *state;
|
struct test_server_st *tss = *state;
|
||||||
@ -344,7 +398,6 @@ static void torture_server_establish_sftp(void **state)
|
|||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void torture_server_test_sftp_function(void **state)
|
static void torture_server_test_sftp_function(void **state)
|
||||||
{
|
{
|
||||||
struct test_server_st *tss = *state;
|
struct test_server_st *tss = *state;
|
||||||
@ -406,6 +459,7 @@ static void torture_server_test_sftp_function(void **state)
|
|||||||
|
|
||||||
rv_str = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
rv_str = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||||
assert_non_null(rv_str);
|
assert_non_null(rv_str);
|
||||||
|
ssh_string_free_char(rv_str);
|
||||||
|
|
||||||
rc = sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
rc = sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
@ -438,6 +492,481 @@ static void torture_server_test_sftp_function(void **state)
|
|||||||
assert_int_equal(rc, SSH_OK);
|
assert_int_equal(rc, SSH_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void torture_server_sftp_open_read_write(void **state)
|
||||||
|
{
|
||||||
|
struct test_server_st *tss = *state;
|
||||||
|
struct torture_state *s;
|
||||||
|
struct torture_sftp *tsftp;
|
||||||
|
sftp_session sftp;
|
||||||
|
ssh_session session;
|
||||||
|
sftp_attributes a = NULL;
|
||||||
|
sftp_file new_file = NULL;
|
||||||
|
char tmp_file[PATH_MAX] = {0};
|
||||||
|
char data[10] = "0123456789";
|
||||||
|
char read_data[10] = {0};
|
||||||
|
struct stat sb;
|
||||||
|
int rc, write_len, read_len;
|
||||||
|
|
||||||
|
assert_non_null(tss);
|
||||||
|
|
||||||
|
s = tss->state;
|
||||||
|
assert_non_null(s);
|
||||||
|
|
||||||
|
session = s->ssh.session;
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
tsftp = s->ssh.tsftp;
|
||||||
|
assert_non_null(tsftp);
|
||||||
|
|
||||||
|
sftp = tsftp->sftp;
|
||||||
|
assert_non_null(sftp);
|
||||||
|
|
||||||
|
snprintf(tmp_file, sizeof(tmp_file), "%s/newfile", tss->temp_dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new file
|
||||||
|
*/
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_WRONLY | O_CREAT, 0751);
|
||||||
|
assert_non_null(new_file);
|
||||||
|
|
||||||
|
/* Write should work ok */
|
||||||
|
write_len = sftp_write(new_file, data, sizeof(data));
|
||||||
|
assert_int_equal(write_len, sizeof(data));
|
||||||
|
|
||||||
|
/* Reading should fail */
|
||||||
|
read_len = sftp_read(new_file, read_data, sizeof(read_data));
|
||||||
|
assert_int_equal(read_len, SSH_ERROR);
|
||||||
|
|
||||||
|
rc = sftp_close(new_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Verify locally the mode is correct */
|
||||||
|
rc = stat(tmp_file, &sb);
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
assert_int_equal(sb.st_mode, S_IFREG | 0751);
|
||||||
|
assert_int_equal(sb.st_size, sizeof(data)); /* 10b written */
|
||||||
|
|
||||||
|
/* Remote stat */
|
||||||
|
a = sftp_stat(sftp, tmp_file);
|
||||||
|
assert_non_null(a);
|
||||||
|
assert_int_equal(a->permissions, S_IFREG | 0751);
|
||||||
|
assert_int_equal(a->size, sizeof(data)); /* 10b written */
|
||||||
|
assert_int_equal(a->type, SSH_FILEXFER_TYPE_REGULAR);
|
||||||
|
sftp_attributes_free(a);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, lets try O_APPEND, mode is ignored
|
||||||
|
*/
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_WRONLY | O_APPEND, 0);
|
||||||
|
assert_non_null(new_file);
|
||||||
|
|
||||||
|
/* fstat is not implemented */
|
||||||
|
a = sftp_fstat(new_file);
|
||||||
|
assert_null(a);
|
||||||
|
|
||||||
|
/* Write should work ok */
|
||||||
|
write_len = sftp_write(new_file, data, sizeof(data));
|
||||||
|
assert_int_equal(write_len, sizeof(data));
|
||||||
|
|
||||||
|
/* Reading should fail */
|
||||||
|
read_len = sftp_read(new_file, read_data, sizeof(read_data));
|
||||||
|
assert_int_equal(read_len, SSH_ERROR);
|
||||||
|
|
||||||
|
rc = sftp_close(new_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, lets try read+write, mode is ignored
|
||||||
|
*/
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_RDWR, 0);
|
||||||
|
assert_non_null(new_file);
|
||||||
|
|
||||||
|
/* Reading should work */
|
||||||
|
read_len = sftp_read(new_file, read_data, sizeof(read_data));
|
||||||
|
assert_int_equal(read_len, sizeof(read_data));
|
||||||
|
assert_int_equal(sizeof(read_data), sizeof(data)); /* sanity */
|
||||||
|
assert_memory_equal(read_data, data, sizeof(data));
|
||||||
|
|
||||||
|
rc = sftp_seek(new_file, 20);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Write should work also ok */
|
||||||
|
write_len = sftp_write(new_file, data, sizeof(data));
|
||||||
|
assert_int_equal(write_len, sizeof(data));
|
||||||
|
|
||||||
|
rc = sftp_close(new_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* Remove the file */
|
||||||
|
rc = sftp_unlink(sftp, tmp_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* again: the file does not exist anymore so we should fail now */
|
||||||
|
rc = sftp_unlink(sftp, tmp_file);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, lets try read+write+create
|
||||||
|
*/
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_RDWR | O_CREAT, 0700);
|
||||||
|
assert_non_null(new_file);
|
||||||
|
|
||||||
|
/* Reading should not fail but return no data */
|
||||||
|
read_len = sftp_read(new_file, read_data, sizeof(read_data));
|
||||||
|
assert_int_equal(read_len, 0);
|
||||||
|
|
||||||
|
rc = sftp_close(new_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* be nice */
|
||||||
|
rc = sftp_unlink(sftp, tmp_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* null flags should be invalid */
|
||||||
|
/* but there is no way in libssh client to force null flags so skip this
|
||||||
|
new_file = sftp_open(sftp, tmp_file, 0, 0700);
|
||||||
|
assert_null(new_file);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Only O_CREAT is invalid on file which does not exist. Read is implicit */
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_CREAT, 0700);
|
||||||
|
assert_null(new_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_server_sftp_mkdir(void **state)
|
||||||
|
{
|
||||||
|
struct test_server_st *tss = *state;
|
||||||
|
struct torture_state *s;
|
||||||
|
struct torture_sftp *tsftp;
|
||||||
|
sftp_session sftp;
|
||||||
|
ssh_session session;
|
||||||
|
sftp_file new_file = NULL;
|
||||||
|
char tmp_dir[PATH_MAX] = {0};
|
||||||
|
char tmp_file[PATH_MAX] = {0};
|
||||||
|
sftp_attributes a = NULL;
|
||||||
|
struct stat sb;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert_non_null(tss);
|
||||||
|
|
||||||
|
s = tss->state;
|
||||||
|
assert_non_null(s);
|
||||||
|
|
||||||
|
session = s->ssh.session;
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
tsftp = s->ssh.tsftp;
|
||||||
|
assert_non_null(tsftp);
|
||||||
|
|
||||||
|
sftp = tsftp->sftp;
|
||||||
|
assert_non_null(sftp);
|
||||||
|
|
||||||
|
snprintf(tmp_dir, sizeof(tmp_dir), "%s/newdir", tss->temp_dir);
|
||||||
|
|
||||||
|
/* create a test dir */
|
||||||
|
rc = sftp_mkdir(sftp, tmp_dir, 0751);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* try the same path again -- we should get an error */
|
||||||
|
rc = sftp_mkdir(sftp, tmp_dir, 0751);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* Verify locally the mode is correct */
|
||||||
|
rc = stat(tmp_dir, &sb);
|
||||||
|
assert_int_equal(rc, 0);
|
||||||
|
assert_int_equal(sb.st_mode, S_IFDIR | 0751);
|
||||||
|
|
||||||
|
/* Remote stat */
|
||||||
|
a = sftp_stat(sftp, tmp_dir);
|
||||||
|
assert_non_null(a);
|
||||||
|
assert_int_equal(a->permissions, S_IFDIR | 0751);
|
||||||
|
assert_int_equal(a->type, SSH_FILEXFER_TYPE_DIRECTORY);
|
||||||
|
sftp_attributes_free(a);
|
||||||
|
|
||||||
|
snprintf(tmp_file, sizeof(tmp_file), "%s/newdir/newfile", tss->temp_dir);
|
||||||
|
|
||||||
|
/* create a file in there */
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_WRONLY | O_CREAT, 0700);
|
||||||
|
assert_non_null(new_file);
|
||||||
|
rc = sftp_close(new_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* remove of non-empty directory fails */
|
||||||
|
rc = sftp_rmdir(sftp, tmp_dir);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* Unlink can not remove directory either */
|
||||||
|
rc = sftp_unlink(sftp, tmp_dir);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* Remove the file */
|
||||||
|
rc = sftp_unlink(sftp, tmp_file);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
|
/* Now it should work */
|
||||||
|
rc = sftp_rmdir(sftp, tmp_dir);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_server_sftp_realpath(void **state)
|
||||||
|
{
|
||||||
|
struct test_server_st *tss = *state;
|
||||||
|
struct torture_state *s;
|
||||||
|
struct torture_sftp *tsftp;
|
||||||
|
sftp_session sftp;
|
||||||
|
ssh_session session;
|
||||||
|
char path[PATH_MAX] = {0};
|
||||||
|
char exp_path[PATH_MAX] = {0};
|
||||||
|
char *new_path = NULL;
|
||||||
|
|
||||||
|
assert_non_null(tss);
|
||||||
|
|
||||||
|
s = tss->state;
|
||||||
|
assert_non_null(s);
|
||||||
|
|
||||||
|
session = s->ssh.session;
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
tsftp = s->ssh.tsftp;
|
||||||
|
assert_non_null(tsftp);
|
||||||
|
|
||||||
|
sftp = tsftp->sftp;
|
||||||
|
assert_non_null(sftp);
|
||||||
|
|
||||||
|
/* first try with the empty string, which should be equivalent to CWD */
|
||||||
|
new_path = sftp_canonicalize_path(sftp, path);
|
||||||
|
assert_non_null(new_path);
|
||||||
|
assert_string_equal(new_path, tss->cwd);
|
||||||
|
ssh_string_free_char(new_path);
|
||||||
|
|
||||||
|
/* now, lets try some more complicated paths relative to the CWD */
|
||||||
|
snprintf(path, sizeof(path), "%s/.././%s",
|
||||||
|
tss->temp_dir, tss->temp_dir);
|
||||||
|
new_path = sftp_canonicalize_path(sftp, path);
|
||||||
|
assert_non_null(new_path);
|
||||||
|
snprintf(exp_path, sizeof(exp_path), "%s/%s",
|
||||||
|
tss->cwd, tss->temp_dir);
|
||||||
|
assert_string_equal(new_path, exp_path);
|
||||||
|
ssh_string_free_char(new_path);
|
||||||
|
|
||||||
|
/* and this one does not exists, which is an error */
|
||||||
|
snprintf(path, sizeof(path), "%s/.././%s/nodir",
|
||||||
|
tss->temp_dir, tss->temp_dir);
|
||||||
|
new_path = sftp_canonicalize_path(sftp, path);
|
||||||
|
assert_null(new_path);
|
||||||
|
ssh_string_free_char(new_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_server_sftp_symlink(void **state)
|
||||||
|
{
|
||||||
|
struct test_server_st *tss = *state;
|
||||||
|
struct torture_state *s;
|
||||||
|
struct torture_sftp *tsftp;
|
||||||
|
sftp_session sftp;
|
||||||
|
ssh_session session;
|
||||||
|
sftp_file new_file = NULL;
|
||||||
|
char tmp_dir[PATH_MAX] = {0};
|
||||||
|
char tmp_file[PATH_MAX] = {0};
|
||||||
|
char path[PATH_MAX] = {0};
|
||||||
|
char abs_path[PATH_MAX] = {0};
|
||||||
|
char data[42] = "012345678901234567890123456789012345678901";
|
||||||
|
char *new_path = NULL;
|
||||||
|
sftp_attributes a = NULL;
|
||||||
|
sftp_dir dir;
|
||||||
|
int write_len, num_files = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert_non_null(tss);
|
||||||
|
|
||||||
|
s = tss->state;
|
||||||
|
assert_non_null(s);
|
||||||
|
|
||||||
|
session = s->ssh.session;
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
tsftp = s->ssh.tsftp;
|
||||||
|
assert_non_null(tsftp);
|
||||||
|
|
||||||
|
sftp = tsftp->sftp;
|
||||||
|
assert_non_null(sftp);
|
||||||
|
|
||||||
|
/* create a test dir */
|
||||||
|
snprintf(tmp_dir, sizeof(tmp_dir), "%s/newdir", tss->temp_dir);
|
||||||
|
rc = sftp_mkdir(sftp, tmp_dir, 0751);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* create a file in there */
|
||||||
|
snprintf(tmp_file, sizeof(tmp_file), "%s/%s/newdir/newfile",
|
||||||
|
tss->cwd, tss->temp_dir);
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_WRONLY | O_CREAT, 0700);
|
||||||
|
assert_non_null(new_file);
|
||||||
|
write_len = sftp_write(new_file, data, sizeof(data));
|
||||||
|
assert_int_equal(write_len, sizeof(data));
|
||||||
|
rc = sftp_close(new_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* now, lets create a (relative) symlink to the new file */
|
||||||
|
snprintf(path, sizeof(path), "%s/newdir/linkname", tss->temp_dir);
|
||||||
|
rc = sftp_symlink(sftp, tmp_file, path);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* when the destination exists, it should fail */
|
||||||
|
rc = sftp_symlink(sftp, tmp_dir, tmp_file);
|
||||||
|
assert_int_equal(rc, SSH_ERROR);
|
||||||
|
|
||||||
|
/* now, there are different versions of stat that follow symlinks or not */
|
||||||
|
/* lstat should not follow the symlink and show information about the link
|
||||||
|
* itself */
|
||||||
|
a = sftp_lstat(sftp, path);
|
||||||
|
assert_non_null(a);
|
||||||
|
assert_int_not_equal(a->size, sizeof(data));
|
||||||
|
assert_int_equal(a->type, SSH_FILEXFER_TYPE_SYMLINK);
|
||||||
|
sftp_attributes_free(a);
|
||||||
|
|
||||||
|
/* readlink should give us more information about the target of the symlink
|
||||||
|
*/
|
||||||
|
new_path = sftp_readlink(sftp, path);
|
||||||
|
assert_non_null(new_path);
|
||||||
|
snprintf(abs_path, sizeof(abs_path), "%s/%s/newdir/newfile",
|
||||||
|
tss->cwd, tss->temp_dir);
|
||||||
|
assert_string_equal(new_path, abs_path);
|
||||||
|
ssh_string_free_char(new_path);
|
||||||
|
|
||||||
|
/* stat should follow the symlink and show information about the link
|
||||||
|
* target */
|
||||||
|
a = sftp_stat(sftp, path);
|
||||||
|
assert_non_null(a);
|
||||||
|
assert_int_equal(a->size, sizeof(data));
|
||||||
|
assert_int_equal(a->permissions, S_IFREG | 0700);
|
||||||
|
assert_int_equal(a->type, SSH_FILEXFER_TYPE_REGULAR);
|
||||||
|
sftp_attributes_free(a);
|
||||||
|
|
||||||
|
/* on non-existing path, they fail */
|
||||||
|
a = sftp_lstat(sftp, "non-existing");
|
||||||
|
assert_null(a);
|
||||||
|
a = sftp_stat(sftp, "non-existing");
|
||||||
|
assert_null(a);
|
||||||
|
|
||||||
|
/**** readdir ****/
|
||||||
|
dir = sftp_opendir(sftp, tmp_dir);
|
||||||
|
assert_non_null(dir);
|
||||||
|
while ((a = sftp_readdir(sftp, dir))) {
|
||||||
|
if (strcmp(a->name, ".") != 0 &&
|
||||||
|
strcmp(a->name, "..") != 0 &&
|
||||||
|
strcmp(a->name, "newfile") != 0 &&
|
||||||
|
strcmp(a->name, "linkname") != 0) {
|
||||||
|
/* There is a file we did not create */
|
||||||
|
assert_true(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
num_files++;
|
||||||
|
sftp_attributes_free(a);
|
||||||
|
}
|
||||||
|
assert_int_equal(num_files, 4);
|
||||||
|
rc = sftp_dir_eof(dir);
|
||||||
|
assert_int_equal(rc, 1);
|
||||||
|
rc = sftp_closedir(dir);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* now, remove the target of the link, the stat should not handle that,
|
||||||
|
* while lstat should keep working */
|
||||||
|
rc = sftp_unlink(sftp, tmp_file);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
|
||||||
|
a = sftp_lstat(sftp, path);
|
||||||
|
assert_non_null(a);
|
||||||
|
assert_int_not_equal(a->size, sizeof(data));
|
||||||
|
sftp_attributes_free(a);
|
||||||
|
|
||||||
|
a = sftp_stat(sftp, path);
|
||||||
|
assert_null(a);
|
||||||
|
|
||||||
|
/* readlink works ok on broken symlinks */
|
||||||
|
new_path = sftp_readlink(sftp, path);
|
||||||
|
assert_non_null(new_path);
|
||||||
|
snprintf(abs_path, sizeof(abs_path), "%s/%s/newdir/newfile",
|
||||||
|
tss->cwd, tss->temp_dir);
|
||||||
|
assert_string_equal(new_path, abs_path);
|
||||||
|
ssh_string_free_char(new_path);
|
||||||
|
|
||||||
|
/* readlink should fail on directories */
|
||||||
|
new_path = sftp_readlink(sftp, tmp_dir);
|
||||||
|
assert_null(new_path);
|
||||||
|
/* readlink should fail on or on non-existing files */
|
||||||
|
new_path = sftp_readlink(sftp, tmp_file);
|
||||||
|
assert_null(new_path);
|
||||||
|
|
||||||
|
/* Clean up symlink */
|
||||||
|
rc = sftp_unlink(sftp, path);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
/* Clean up temporary directory */
|
||||||
|
rc = sftp_rmdir(sftp, tmp_dir);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void torture_server_sftp_extended(void **state)
|
||||||
|
{
|
||||||
|
struct test_server_st *tss = *state;
|
||||||
|
struct torture_state *s;
|
||||||
|
struct torture_sftp *tsftp;
|
||||||
|
sftp_session sftp;
|
||||||
|
ssh_session session;
|
||||||
|
sftp_file new_file = NULL;
|
||||||
|
char tmp_dir[PATH_MAX] = {0};
|
||||||
|
char tmp_file[PATH_MAX] = {0};
|
||||||
|
sftp_statvfs_t st = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert_non_null(tss);
|
||||||
|
|
||||||
|
s = tss->state;
|
||||||
|
assert_non_null(s);
|
||||||
|
|
||||||
|
session = s->ssh.session;
|
||||||
|
assert_non_null(session);
|
||||||
|
|
||||||
|
tsftp = s->ssh.tsftp;
|
||||||
|
assert_non_null(tsftp);
|
||||||
|
|
||||||
|
sftp = tsftp->sftp;
|
||||||
|
assert_non_null(sftp);
|
||||||
|
|
||||||
|
/* create a test dir */
|
||||||
|
snprintf(tmp_dir, sizeof(tmp_dir), "%s/newdir", tss->temp_dir);
|
||||||
|
rc = sftp_mkdir(sftp, tmp_dir, 0751);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* create a file in there */
|
||||||
|
snprintf(tmp_file, sizeof(tmp_file), "%s/%s/newdir/newfile",
|
||||||
|
tss->cwd, tss->temp_dir);
|
||||||
|
new_file = sftp_open(sftp, tmp_file, O_WRONLY | O_CREAT, 0700);
|
||||||
|
assert_non_null(new_file);
|
||||||
|
|
||||||
|
/* extended fstatvsf is not advertised nor supported now but calling this
|
||||||
|
* message will keep hanging the server. The extension protocol says that
|
||||||
|
* the clients can not request extension that are not supported by the
|
||||||
|
* server so before doing this, we should use sftp_extension_supported()
|
||||||
|
* anyway */
|
||||||
|
/* st = sftp_fstatvfs(new_file);
|
||||||
|
assert_null(st); */
|
||||||
|
|
||||||
|
/* close */
|
||||||
|
rc = sftp_close(new_file);
|
||||||
|
assert_ssh_return_code(session, rc);
|
||||||
|
|
||||||
|
/* extended statvsf */
|
||||||
|
st = sftp_statvfs(sftp, tmp_file);
|
||||||
|
assert_non_null(st);
|
||||||
|
/* probably hard to check more */
|
||||||
|
sftp_statvfs_free(st);
|
||||||
|
|
||||||
|
/* Clean up temporary directory */
|
||||||
|
rc = sftp_unlink(sftp, tmp_file);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
rc = sftp_rmdir(sftp, tmp_dir);
|
||||||
|
assert_int_equal(rc, SSH_OK);
|
||||||
|
}
|
||||||
|
|
||||||
int torture_run_tests(void) {
|
int torture_run_tests(void) {
|
||||||
int rc;
|
int rc;
|
||||||
struct CMUnitTest tests[] = {
|
struct CMUnitTest tests[] = {
|
||||||
@ -447,6 +976,21 @@ int torture_run_tests(void) {
|
|||||||
cmocka_unit_test_setup_teardown(torture_server_test_sftp_function,
|
cmocka_unit_test_setup_teardown(torture_server_test_sftp_function,
|
||||||
session_setup,
|
session_setup,
|
||||||
session_teardown),
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_server_sftp_open_read_write,
|
||||||
|
session_setup_sftp,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_server_sftp_mkdir,
|
||||||
|
session_setup_sftp,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_server_sftp_realpath,
|
||||||
|
session_setup_sftp,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_server_sftp_symlink,
|
||||||
|
session_setup_sftp,
|
||||||
|
session_teardown),
|
||||||
|
cmocka_unit_test_setup_teardown(torture_server_sftp_extended,
|
||||||
|
session_setup_sftp,
|
||||||
|
session_teardown),
|
||||||
};
|
};
|
||||||
|
|
||||||
ssh_init();
|
ssh_init();
|
||||||
|
Reference in New Issue
Block a user