mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-07-31 00:03:07 +03:00
sftp: fix problems in sftp APIs and example
Signed-off-by: tatataeki <shengzeyu19_98@163.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org> Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
This commit is contained in:
@ -43,13 +43,8 @@ The goal is to show the API in action.
|
||||
#include <stdbool.h>
|
||||
|
||||
/* below are for sftp */
|
||||
#include <sys/types.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
@ -146,9 +141,9 @@ const struct message_handler extended_handlers[] = {
|
||||
|
||||
struct sftp_handle s_handle_table[MAX_HANDLE_NUM];
|
||||
|
||||
static void init_handle_table(int handle_num) {
|
||||
static void init_handle_table(void) {
|
||||
int obj_size = sizeof(struct sftp_handle);
|
||||
memset(s_handle_table, 0, obj_size*handle_num);
|
||||
memset(s_handle_table, 0, obj_size * MAX_HANDLE_NUM);
|
||||
}
|
||||
|
||||
static void reinit_single_handle(struct sftp_handle* handle) {
|
||||
@ -159,11 +154,11 @@ static void reinit_single_handle(struct sftp_handle* handle) {
|
||||
handle->fd = -1;
|
||||
}
|
||||
|
||||
static int handle_is_ok(int i, int type) {
|
||||
return i >= 0 && (u_int)i < MAX_HANDLE_NUM && s_handle_table[i].type == type;
|
||||
static int handle_is_ok(uint8_t i, int type) {
|
||||
return i < MAX_HANDLE_NUM && s_handle_table[i].type == type;
|
||||
}
|
||||
|
||||
static int handle_close(int handle_ind) {
|
||||
static int handle_close(uint8_t handle_ind) {
|
||||
int ret = SSH_ERROR;
|
||||
|
||||
if (handle_is_ok(handle_ind, FILE_HANDLE)) {
|
||||
@ -202,9 +197,9 @@ static int handle_close_by_pointer(struct sftp_handle* handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_handles(int handle_num) {
|
||||
int i;
|
||||
for(i = 0; i < handle_num; i++) {
|
||||
static void free_handles(void) {
|
||||
uint8_t i;
|
||||
for(i = 0; i < MAX_HANDLE_NUM; i++) {
|
||||
handle_close(i);
|
||||
/* reinit this handle */
|
||||
reinit_single_handle(&s_handle_table[i]);
|
||||
@ -213,8 +208,8 @@ static void free_handles(int handle_num) {
|
||||
}
|
||||
|
||||
static int add_handle(int type, void *dirp, int fd, const char *name, void *session_id) {
|
||||
int ret = SSH_ERROR;
|
||||
int i;
|
||||
int ret = -1;
|
||||
uint8_t i;
|
||||
if (dirp == NULL && fd < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -240,12 +235,10 @@ static int add_handle(int type, void *dirp, int fd, const char *name, void *sess
|
||||
}
|
||||
|
||||
static char* get_handle_name(struct sftp_handle* handle) {
|
||||
char *ret = NULL;
|
||||
|
||||
if (handle != NULL && handle->name != NULL)
|
||||
ret = handle->name;
|
||||
|
||||
return ret;
|
||||
return handle->name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* ssh_str_error(int u_errno) {
|
||||
@ -255,7 +248,7 @@ static const char* ssh_str_error(int u_errno) {
|
||||
return "No such file";
|
||||
case SSH_FX_PERMISSION_DENIED:
|
||||
return "Permission denied";
|
||||
case SSH_FX_BAD_MESSAGE:
|
||||
case SSH_FX_BAD_MESSAGE:
|
||||
return "Bad message";
|
||||
case SSH_FX_OP_UNSUPPORTED:
|
||||
return "Operation not supported";
|
||||
@ -299,8 +292,7 @@ static int unix_errno_to_ssh_stat(int u_errno) {
|
||||
|
||||
static void stat_to_filexfer_attrib(const struct stat* z_st, struct sftp_attributes_struct* z_attr)
|
||||
{
|
||||
z_attr->flags = 0;
|
||||
z_attr->flags |= (uint32_t)SSH_FILEXFER_ATTR_SIZE;
|
||||
z_attr->flags = 0 | (uint32_t)SSH_FILEXFER_ATTR_SIZE;
|
||||
z_attr->size = z_st->st_size;
|
||||
|
||||
z_attr->flags |= (uint32_t)SSH_FILEXFER_ATTR_UIDGID;
|
||||
@ -395,7 +387,7 @@ static int readdir_long_name(char* z_file_name, struct stat* z_st, char* z_long_
|
||||
*ptr++ = 'x';
|
||||
else
|
||||
*ptr++ = '-';
|
||||
|
||||
|
||||
*ptr++ = ' ';
|
||||
*ptr = '\0';
|
||||
|
||||
@ -415,7 +407,6 @@ static int readdir_long_name(char* z_file_name, struct stat* z_st, char* z_long_
|
||||
}
|
||||
|
||||
static int process_open(sftp_client_message client_msg) {
|
||||
int ret = SSH_OK;
|
||||
const char *filename = sftp_client_message_get_filename(client_msg);
|
||||
uint32_t msg_flag = sftp_client_message_get_flags(client_msg);
|
||||
int file_flag;
|
||||
@ -423,7 +414,7 @@ static int process_open(sftp_client_message client_msg) {
|
||||
int handle_ind = -1;
|
||||
int status;
|
||||
|
||||
if (((msg_flag&(uint32_t)SSH_FXF_READ) == SSH_FXF_READ) &&
|
||||
if (((msg_flag&(uint32_t)SSH_FXF_READ) == SSH_FXF_READ) &&
|
||||
((msg_flag&(uint32_t)SSH_FXF_WRITE) == SSH_FXF_WRITE)) {
|
||||
file_flag = O_RDWR; //file must exist
|
||||
if ((msg_flag & (uint32_t)SSH_FXF_CREAT) == SSH_FXF_CREAT)
|
||||
@ -439,17 +430,15 @@ static int process_open(sftp_client_message client_msg) {
|
||||
} else {
|
||||
printf("undefined message flag\n");
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, "Flag error");
|
||||
ret = SSH_ERROR;
|
||||
return ret;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
fd = open(filename, file_flag, 0600);
|
||||
if(fd == -1){
|
||||
status = unix_errno_to_ssh_stat(errno);
|
||||
printf("error open file with error: %d\n", errno);
|
||||
printf("error opening file with error: %d\n", errno);
|
||||
sftp_reply_status(client_msg, status, "Write error");
|
||||
ret = SSH_ERROR;
|
||||
return ret;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
handle_ind = add_handle(FILE_HANDLE, NULL, fd, filename, client_msg->sftp);
|
||||
@ -458,18 +447,16 @@ static int process_open(sftp_client_message client_msg) {
|
||||
ssh_string handle_s = sftp_handle_alloc(client_msg->sftp, handle_ptr);
|
||||
sftp_reply_handle(client_msg, handle_s);
|
||||
ssh_string_free(handle_s);
|
||||
ret = SSH_OK;
|
||||
}else {
|
||||
close(fd);
|
||||
printf("opening file failed");
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, "No handle available");
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int process_read(sftp_client_message client_msg) {
|
||||
int ret = SSH_OK;
|
||||
struct sftp_handle *client_handle = (struct sftp_handle*)sftp_handle(client_msg->sftp, client_msg->handle);
|
||||
uint32_t readn;
|
||||
int fd;
|
||||
@ -477,7 +464,7 @@ static int process_read(sftp_client_message client_msg) {
|
||||
int rv;
|
||||
|
||||
if (client_handle == NULL || client_handle->session_id != client_msg->sftp) {
|
||||
printf("get wrong handle from msg\n");
|
||||
printf("got wrong handle from msg\n");
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, NULL);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@ -487,18 +474,16 @@ static int process_read(sftp_client_message client_msg) {
|
||||
if (fd < 0) {
|
||||
sftp_reply_status(client_msg, SSH_FX_INVALID_HANDLE, NULL);
|
||||
printf("error reading file fd: %d\n", fd);
|
||||
ret = SSH_ERROR;
|
||||
return ret;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rv = lseek(fd, client_msg->offset, SEEK_SET);
|
||||
if (rv == -1) {
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, NULL);
|
||||
printf("error seeking file fd: %d at offset: %" PRIu64 "\n", fd, client_msg->offset);
|
||||
ret = SSH_ERROR;
|
||||
return ret;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
buffer = malloc((client_msg->len)*sizeof(char));
|
||||
buffer = malloc(client_msg->len);
|
||||
readn = read(fd, buffer, client_msg->len);
|
||||
|
||||
if(readn > 0){
|
||||
@ -508,14 +493,16 @@ static int process_read(sftp_client_message client_msg) {
|
||||
}else {
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, NULL);
|
||||
printf("read file error!\n");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return ret;
|
||||
|
||||
free(buffer);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int process_write(sftp_client_message client_msg) {
|
||||
int ret = SSH_OK;
|
||||
struct sftp_handle *client_handle = (struct sftp_handle*)sftp_handle(client_msg->sftp, client_msg->handle);
|
||||
uint32_t writen;
|
||||
int written;
|
||||
int fd;
|
||||
const char *msg_data;
|
||||
uint32_t len;
|
||||
@ -532,8 +519,7 @@ static int process_write(sftp_client_message client_msg) {
|
||||
if (fd < 0) {
|
||||
sftp_reply_status(client_msg, SSH_FX_INVALID_HANDLE, NULL);
|
||||
printf("write file fd error!\n");
|
||||
ret = SSH_ERROR;
|
||||
return ret;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
msg_data = ssh_string_get_char(client_msg->data);
|
||||
@ -544,19 +530,21 @@ static int process_write(sftp_client_message client_msg) {
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, NULL);
|
||||
printf("error seeking file at offset: %" PRIu64 "\n", client_msg->offset);
|
||||
}
|
||||
writen = write(fd, msg_data, len);
|
||||
if(writen == len) {
|
||||
written = write(fd, msg_data, len);
|
||||
if (written == (int)len) {
|
||||
sftp_reply_status(client_msg, SSH_FX_OK, NULL);
|
||||
}else {
|
||||
} else if (written == -1) {
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, "Write error");
|
||||
} else {
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, "Partial write");
|
||||
}
|
||||
|
||||
return ret;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int process_close(sftp_client_message client_msg) {
|
||||
int ret = SSH_OK;
|
||||
struct sftp_handle *client_handle = (struct sftp_handle*)sftp_handle(client_msg->sftp, client_msg->handle);
|
||||
int ret;
|
||||
|
||||
if (client_handle == NULL) {
|
||||
printf("get wrong handle from msg\n");
|
||||
@ -564,19 +552,18 @@ static int process_close(sftp_client_message client_msg) {
|
||||
}
|
||||
|
||||
ret = handle_close_by_pointer(client_handle);
|
||||
reinit_single_handle(client_handle);
|
||||
if (ret == SSH_OK) {
|
||||
reinit_single_handle(client_handle);
|
||||
sftp_reply_status(client_msg, SSH_FX_OK, NULL);
|
||||
} else {
|
||||
printf("closing file failed\n");
|
||||
sftp_reply_status(client_msg, SSH_FX_BAD_MESSAGE, "Invalid handle");
|
||||
}
|
||||
|
||||
return ret;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int process_opendir(sftp_client_message client_msg) {
|
||||
int ret = SSH_OK;
|
||||
DIR *dir = NULL;
|
||||
const char *dir_name = sftp_client_message_get_filename(client_msg);
|
||||
int handle_ind = -1;
|
||||
@ -592,13 +579,12 @@ static int process_opendir(sftp_client_message client_msg) {
|
||||
ssh_string handle_s = sftp_handle_alloc(client_msg->sftp, &s_handle_table[handle_ind]);
|
||||
sftp_reply_handle(client_msg, handle_s);
|
||||
ssh_string_free(handle_s);
|
||||
ret = SSH_OK;
|
||||
} else {
|
||||
closedir(dir);
|
||||
sftp_reply_status(client_msg, SSH_FX_FAILURE, "No handle available");
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int process_readdir(sftp_client_message client_msg) {
|
||||
@ -610,6 +596,7 @@ static int process_readdir(sftp_client_message client_msg) {
|
||||
|
||||
char long_path[PATH_MAX];
|
||||
int path_length;
|
||||
int srclen;
|
||||
char *handle_name;
|
||||
|
||||
if (client_handle == NULL || client_handle->session_id != client_msg->sftp) {
|
||||
@ -622,18 +609,23 @@ static int process_readdir(sftp_client_message client_msg) {
|
||||
if (dir == NULL) {
|
||||
sftp_reply_status(client_msg, SSH_FX_INVALID_HANDLE, NULL);
|
||||
printf("read dir handle error!\n");
|
||||
ret = SSH_ERROR;
|
||||
return ret;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ret = SSH_OK;
|
||||
handle_name = get_handle_name(client_handle);
|
||||
if (handle_name == NULL) {
|
||||
sftp_reply_status(client_msg, SSH_FX_INVALID_HANDLE, NULL);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
strcpy(long_path, handle_name);
|
||||
strcat(long_path, "/");
|
||||
|
||||
srclen = strlen(handle_name);
|
||||
if (srclen + 2 >= PATH_MAX) {
|
||||
printf("handle string length exceed max length!\n");
|
||||
sftp_reply_status(client_msg, SSH_FX_INVALID_HANDLE, NULL);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
strncpy(long_path, handle_name, PATH_MAX-strlen(long_path)-1);
|
||||
strncat(long_path, "/", PATH_MAX-strlen(long_path)-1);
|
||||
path_length = (int)strlen(long_path);
|
||||
|
||||
for(int i=0; i < MAX_ENTRIES_NUM_IN_PACKET; i++) {
|
||||
@ -644,7 +636,12 @@ static int process_readdir(sftp_client_message client_msg) {
|
||||
struct stat st;
|
||||
char long_name[MAX_LONG_NAME_LEN];
|
||||
|
||||
strcpy(&long_path[path_length], dentry->d_name);
|
||||
if (strlen(dentry->d_name)+path_length+1 >= PATH_MAX) {
|
||||
printf("handle string length exceed max length!\n");
|
||||
sftp_reply_status(client_msg, SSH_FX_INVALID_HANDLE, NULL);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
strncpy(&long_path[path_length], dentry->d_name, strlen(dentry->d_name)+1);
|
||||
|
||||
if(lstat(long_path, &st) == 0) {
|
||||
stat_to_filexfer_attrib(&st, &attr);
|
||||
@ -658,7 +655,7 @@ static int process_readdir(sftp_client_message client_msg) {
|
||||
} else {
|
||||
printf("readdir long name error\n");
|
||||
}
|
||||
|
||||
|
||||
entries++;
|
||||
} else {
|
||||
break;
|
||||
@ -695,7 +692,7 @@ static int process_mkdir(sftp_client_message client_msg) {
|
||||
}
|
||||
|
||||
sftp_reply_status(client_msg, status, NULL);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -717,7 +714,7 @@ static int process_rmdir(sftp_client_message client_msg) {
|
||||
}
|
||||
|
||||
sftp_reply_status(client_msg, status, NULL);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -743,7 +740,7 @@ static int process_lstat(sftp_client_message client_msg) {
|
||||
stat_to_filexfer_attrib(&st, &attr);
|
||||
sftp_reply_attr(client_msg, &attr);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -782,7 +779,7 @@ static int process_symlink(sftp_client_message client_msg) {
|
||||
int status = SSH_FX_OK;
|
||||
int rv;
|
||||
// printf("try to create link with src: %s and dest: %s \n", srcpath, destpath);
|
||||
|
||||
|
||||
if (srcpath == NULL || destpath == NULL) {
|
||||
sftp_reply_status(client_msg, SSH_FX_NO_SUCH_FILE, "File name error");
|
||||
return SSH_ERROR;
|
||||
@ -815,19 +812,17 @@ static int process_remove(sftp_client_message client_msg) {
|
||||
}
|
||||
|
||||
sftp_reply_status(client_msg, status, NULL);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int process_unsupposed(sftp_client_message client_msg) {
|
||||
int ret = SSH_OK;
|
||||
sftp_reply_status(client_msg, SSH_FX_OP_UNSUPPORTED, "Operation not supported");
|
||||
printf("Message type %d not implemented\n", sftp_client_message_get_type(client_msg));
|
||||
return ret;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int process_extended_statvfs(sftp_client_message client_msg) {
|
||||
int ret = SSH_OK;
|
||||
const char *path = sftp_client_message_get_filename(client_msg);
|
||||
struct statvfs st;
|
||||
int status;
|
||||
@ -839,36 +834,35 @@ static int process_extended_statvfs(sftp_client_message client_msg) {
|
||||
u_int64_t flag;
|
||||
|
||||
sftp_statvfs = calloc(1, sizeof(struct sftp_statvfs_struct));
|
||||
if (sftp_statvfs == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
flag = (st.f_flag & ST_RDONLY) ? SSH_FXE_STATVFS_ST_RDONLY : 0;
|
||||
flag |= (st.f_flag & ST_NOSUID) ? SSH_FXE_STATVFS_ST_NOSUID : 0;
|
||||
if (sftp_statvfs != NULL) {
|
||||
flag = (st.f_flag & ST_RDONLY) ? SSH_FXE_STATVFS_ST_RDONLY : 0;
|
||||
flag |= (st.f_flag & ST_NOSUID) ? SSH_FXE_STATVFS_ST_NOSUID : 0;
|
||||
|
||||
sftp_statvfs->f_bsize = st.f_bsize;
|
||||
sftp_statvfs->f_frsize = st.f_frsize;
|
||||
sftp_statvfs->f_blocks = st.f_blocks;
|
||||
sftp_statvfs->f_bfree = st.f_bfree;
|
||||
sftp_statvfs->f_bavail = st.f_bavail;
|
||||
sftp_statvfs->f_files = st.f_files;
|
||||
sftp_statvfs->f_ffree = st.f_ffree;
|
||||
sftp_statvfs->f_favail = st.f_favail;
|
||||
sftp_statvfs->f_fsid = st.f_fsid;
|
||||
sftp_statvfs->f_flag = flag;
|
||||
sftp_statvfs->f_namemax = st.f_namemax;
|
||||
|
||||
if(sftp_reply_statvfs(client_msg, sftp_statvfs) == 0)
|
||||
return ret;
|
||||
sftp_statvfs->f_bsize = st.f_bsize;
|
||||
sftp_statvfs->f_frsize = st.f_frsize;
|
||||
sftp_statvfs->f_blocks = st.f_blocks;
|
||||
sftp_statvfs->f_bfree = st.f_bfree;
|
||||
sftp_statvfs->f_bavail = st.f_bavail;
|
||||
sftp_statvfs->f_files = st.f_files;
|
||||
sftp_statvfs->f_ffree = st.f_ffree;
|
||||
sftp_statvfs->f_favail = st.f_favail;
|
||||
sftp_statvfs->f_fsid = st.f_fsid;
|
||||
sftp_statvfs->f_flag = flag;
|
||||
sftp_statvfs->f_namemax = st.f_namemax;
|
||||
|
||||
rv = sftp_reply_statvfs(client_msg, sftp_statvfs);
|
||||
free(sftp_statvfs);
|
||||
if (rv == 0) {
|
||||
return SSH_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
status = unix_errno_to_ssh_stat(errno);
|
||||
ret = SSH_ERROR;
|
||||
sftp_reply_status(client_msg, status, NULL);
|
||||
|
||||
printf("statvfs send failed!\n");
|
||||
return ret;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int process_extended(sftp_client_message sftp_msg) {
|
||||
@ -890,8 +884,6 @@ static int process_extended(sftp_client_message sftp_msg) {
|
||||
sftp_reply_status(sftp_msg, SSH_FX_OP_UNSUPPORTED, "Extended Operation not supported");
|
||||
printf("Extended Message type %s not implemented\n", subtype);
|
||||
return SSH_OK;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int dispatch_sftp_request(sftp_client_message sftp_msg) {
|
||||
@ -905,17 +897,16 @@ static int dispatch_sftp_request(sftp_client_message sftp_msg) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (handler!=NULL)
|
||||
status = handler(sftp_msg);
|
||||
else
|
||||
goto not_implemented;
|
||||
|
||||
return status;
|
||||
|
||||
not_implemented:
|
||||
sftp_reply_status(sftp_msg, SSH_FX_OP_UNSUPPORTED, "Operation not supported");
|
||||
printf("Message type %d not implemented\n", sft_msg_type);
|
||||
return SSH_OK;
|
||||
if (handler!=NULL) {
|
||||
status = handler(sftp_msg);
|
||||
} else {
|
||||
sftp_reply_status(sftp_msg, SSH_FX_OP_UNSUPPORTED, "Operation not supported");
|
||||
printf("Message type %d not implemented\n", sft_msg_type);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int process_client_message(sftp_client_message client_msg) {
|
||||
@ -932,7 +923,6 @@ static int process_client_message(sftp_client_message client_msg) {
|
||||
status = dispatch_sftp_request(client_msg);
|
||||
}
|
||||
|
||||
// status = dispatch_sftp_request(client_msg);
|
||||
if (status!=SSH_OK)
|
||||
printf("error occur in process client message!\n");
|
||||
|
||||
@ -1152,12 +1142,12 @@ static int data_function(ssh_session session, ssh_channel channel, void *data,
|
||||
if(decode_len == -1)
|
||||
return -1;
|
||||
|
||||
msg = sftp_get_client_message_from_packet(cdata->sftp);
|
||||
msg = sftp_get_client_message_from_packet(sftp);
|
||||
rc = process_client_message(msg);
|
||||
sftp_client_message_free(msg);
|
||||
if(rc != SSH_OK)
|
||||
printf("process sftp failed!\n");
|
||||
|
||||
|
||||
return decode_len;
|
||||
}
|
||||
|
||||
@ -1169,7 +1159,7 @@ static int subsystem_request(ssh_session session, ssh_channel channel,
|
||||
|
||||
/* initialize sftp session and file handler */
|
||||
cdata->sftp = sftp_server_new(session, channel);
|
||||
init_handle_table(MAX_HANDLE_NUM);
|
||||
init_handle_table();
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@ -1180,8 +1170,6 @@ static int auth_password(ssh_session session, const char *user,
|
||||
const char *pass, void *userdata) {
|
||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||
|
||||
(void) session;
|
||||
|
||||
if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0) {
|
||||
sdata->authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
@ -1199,9 +1187,6 @@ static int auth_publickey(ssh_session session,
|
||||
{
|
||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||
|
||||
(void) user;
|
||||
(void) session;
|
||||
|
||||
if (signature_state == SSH_PUBLICKEY_STATE_NONE) {
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
@ -1339,8 +1324,8 @@ static void handle_session(ssh_event event, ssh_session session) {
|
||||
|
||||
} while(ssh_channel_is_open(sdata.channel) &&
|
||||
(cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
|
||||
|
||||
free_handles(MAX_HANDLE_NUM);
|
||||
|
||||
free_handles();
|
||||
|
||||
ssh_channel_send_eof(sdata.channel);
|
||||
ssh_channel_close(sdata.channel);
|
||||
@ -1353,7 +1338,6 @@ static void handle_session(ssh_event event, ssh_session session) {
|
||||
|
||||
/* SIGCHLD handler for cleaning up dead children. */
|
||||
static void sigchld_handler(int signo) {
|
||||
(void) signo;
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
}
|
||||
|
||||
@ -1376,13 +1360,13 @@ int main(int argc, char **argv) {
|
||||
rc = ssh_init();
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "ssh_init failed\n");
|
||||
return 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sshbind = ssh_bind_new();
|
||||
if (sshbind == NULL) {
|
||||
fprintf(stderr, "ssh_bind_new failed\n");
|
||||
return 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
@ -1396,7 +1380,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
if(ssh_bind_listen(sshbind) < 0) {
|
||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||
return 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
@ -1442,6 +1426,7 @@ int main(int argc, char **argv) {
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
exit:
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
|
29
src/sftp.c
29
src/sftp.c
@ -356,7 +356,6 @@ void sftp_server_free(sftp_session sftp)
|
||||
|
||||
int sftp_process_init_packet(sftp_client_message client_msg)
|
||||
{
|
||||
int ret = SSH_OK;
|
||||
sftp_session sftp = client_msg->sftp;
|
||||
ssh_session session = sftp->session;
|
||||
int version;
|
||||
@ -384,7 +383,8 @@ int sftp_process_init_packet(sftp_client_message client_msg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sftp_packet_write(sftp, SSH_FXP_VERSION, reply) < 0) {
|
||||
rc = sftp_packet_write(sftp, SSH_FXP_VERSION, reply);
|
||||
if (rc < 0) {
|
||||
SSH_BUFFER_FREE(reply);
|
||||
return -1;
|
||||
}
|
||||
@ -395,10 +395,10 @@ int sftp_process_init_packet(sftp_client_message client_msg)
|
||||
if (version > LIBSFTP_VERSION) {
|
||||
sftp->version = LIBSFTP_VERSION;
|
||||
} else {
|
||||
sftp->version = (int)version;
|
||||
sftp->version = version;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
#endif /* WITH_SERVER */
|
||||
@ -443,26 +443,35 @@ int sftp_decode_channel_data_to_packet(sftp_session sftp, void *data)
|
||||
int offset;
|
||||
int to_read;
|
||||
|
||||
if(packet->sftp == NULL)
|
||||
if (packet->sftp == NULL) {
|
||||
packet->sftp = sftp;
|
||||
}
|
||||
|
||||
packet->type = *((uint8_t *)data + sizeof(uint32_t));
|
||||
payload_len = PULL_BE_U32(data, 0);
|
||||
|
||||
/* We should check the legality of payload length */
|
||||
if(payload_len > MAX_PACKET_LEN || payload_len < 0)
|
||||
if (payload_len > MAX_PACKET_LEN || payload_len < 0) {
|
||||
return SSH_ERROR;
|
||||
|
||||
}
|
||||
|
||||
offset = sizeof(int) + sizeof(uint8_t);
|
||||
to_read = payload_len - sizeof(uint8_t);
|
||||
ssh_buffer_add_data(packet->payload, (void*)((uint8_t *)data + offset), payload_len - sizeof(uint8_t));
|
||||
ssh_buffer_add_data(packet->payload,
|
||||
(void*)((uint8_t *)data + offset),
|
||||
payload_len - sizeof(uint8_t));
|
||||
nread = ssh_buffer_get_len(packet->payload);
|
||||
|
||||
/* We should check if we copied the whole data */
|
||||
if(nread != to_read)
|
||||
if (nread != to_read) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return payload_len + sizeof(int);
|
||||
/*
|
||||
* We should return how many bytes we decoded, including packet length header
|
||||
* and the payload length.
|
||||
*/
|
||||
return payload_len + sizeof(uint32_t);
|
||||
}
|
||||
|
||||
int sftp_packet_write(sftp_session sftp, uint8_t type, ssh_buffer payload)
|
||||
|
@ -266,9 +266,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
|
||||
packet = sftp->read_packet;
|
||||
if (packet == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
payload = packet->payload;
|
||||
@ -278,21 +276,17 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
/* take a copy of the whole packet */
|
||||
msg->complete_message = ssh_buffer_new();
|
||||
if (msg->complete_message == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_data(msg->complete_message,
|
||||
ssh_buffer_get(payload),
|
||||
ssh_buffer_get_len(payload));
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (msg->type!=SSH_FXP_INIT) {
|
||||
if (msg->type != SSH_FXP_INIT) {
|
||||
ssh_buffer_get_u32(payload, &msg->id);
|
||||
}
|
||||
|
||||
@ -302,21 +296,17 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
"d",
|
||||
&version);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
printf("unpack init failed!\n");
|
||||
return NULL;
|
||||
printf("unpack init failed!\n");
|
||||
goto error;
|
||||
}
|
||||
version = ntohl(version);
|
||||
sftp->client_version = (int)version;
|
||||
sftp->client_version = version;
|
||||
break;
|
||||
case SSH_FXP_CLOSE:
|
||||
case SSH_FXP_READDIR:
|
||||
msg->handle = ssh_buffer_get_ssh_string(payload);
|
||||
if (msg->handle == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_READ:
|
||||
@ -326,9 +316,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
&msg->offset,
|
||||
&msg->len);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_WRITE:
|
||||
@ -338,9 +326,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
&msg->offset,
|
||||
&msg->data);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_REMOVE:
|
||||
@ -352,9 +338,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
"s",
|
||||
&msg->filename);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_RENAME:
|
||||
@ -364,9 +348,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
&msg->filename,
|
||||
&msg->data);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_MKDIR:
|
||||
@ -375,29 +357,21 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
"s",
|
||||
&msg->filename);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||
if (msg->attr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_FSETSTAT:
|
||||
msg->handle = ssh_buffer_get_ssh_string(payload);
|
||||
if (msg->handle == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||
if (msg->attr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_LSTAT:
|
||||
@ -406,9 +380,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
"s",
|
||||
&msg->filename);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
if(sftp->version > 3) {
|
||||
ssh_buffer_unpack(payload, "d", &msg->flags);
|
||||
@ -420,15 +392,11 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
&msg->filename,
|
||||
&msg->flags);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
msg->attr = sftp_parse_attr(sftp, payload, 0);
|
||||
if (msg->attr == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_FSTAT:
|
||||
@ -436,9 +404,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
"S",
|
||||
&msg->handle);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SSH_FXP_EXTENDED:
|
||||
@ -446,9 +412,7 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
"s",
|
||||
&msg->submessage);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (strcmp(msg->submessage, "hardlink@openssh.com") == 0 ||
|
||||
@ -458,18 +422,14 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
&msg->filename,
|
||||
&msg->data);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
} else if (strcmp(msg->submessage, "statvfs@openssh.com") == 0 ){
|
||||
rc = ssh_buffer_unpack(payload,
|
||||
"s",
|
||||
&msg->filename);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -481,6 +441,11 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp)
|
||||
}
|
||||
|
||||
return msg;
|
||||
|
||||
error:
|
||||
ssh_set_error_oom(session);
|
||||
sftp_client_message_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -722,8 +687,8 @@ int sftp_reply_data(sftp_client_message msg, const void *data, int len) {
|
||||
|
||||
int sftp_reply_statvfs(sftp_client_message msg, sftp_statvfs_t st)
|
||||
{
|
||||
int ret = 0;
|
||||
ssh_buffer out;
|
||||
|
||||
out = ssh_buffer_new();
|
||||
if (out == NULL) {
|
||||
return -1;
|
||||
@ -742,12 +707,11 @@ int sftp_reply_statvfs(sftp_client_message msg, sftp_statvfs_t st)
|
||||
ssh_buffer_add_u64(out, ntohll(st->f_flag)) < 0 ||
|
||||
ssh_buffer_add_u64(out, ntohll(st->f_namemax)) < 0 ||
|
||||
sftp_packet_write(msg->sftp, SSH_FXP_EXTENDED_REPLY, out) < 0) {
|
||||
SSH_BUFFER_FREE(out);
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
SSH_BUFFER_FREE(out);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,470 +1,470 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2018 by Red Hat, Inc.
|
||||
*
|
||||
* Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "torture.h"
|
||||
#include "torture_key.h"
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#include "test_server.h"
|
||||
#include "default_cb.h"
|
||||
|
||||
#define TORTURE_KNOWN_HOSTS_FILE "libssh_torture_knownhosts"
|
||||
|
||||
const char template[] = "temp_dir_XXXXXX";
|
||||
|
||||
struct test_server_st {
|
||||
struct torture_state *state;
|
||||
struct server_state_st *ss;
|
||||
char *cwd;
|
||||
char *temp_dir;
|
||||
};
|
||||
|
||||
void sftp_handle_session_cb(ssh_event event,
|
||||
ssh_session session,
|
||||
struct server_state_st *state);
|
||||
|
||||
static int setup_default_server(void **state)
|
||||
{
|
||||
struct torture_state *s;
|
||||
struct server_state_st *ss;
|
||||
struct test_server_st *tss;
|
||||
#ifdef HAVE_DSA
|
||||
char dsa_hostkey[1024];
|
||||
#endif /* HAVE_DSA */
|
||||
|
||||
char ed25519_hostkey[1024] = {0};
|
||||
char rsa_hostkey[1024];
|
||||
char ecdsa_hostkey[1024];
|
||||
//char trusted_ca_pubkey[1024];
|
||||
|
||||
char sshd_path[1024];
|
||||
int rc;
|
||||
|
||||
char pid_str[1024];
|
||||
|
||||
pid_t pid;
|
||||
|
||||
assert_non_null(state);
|
||||
|
||||
tss = (struct test_server_st*)calloc(1, sizeof(struct test_server_st));
|
||||
assert_non_null(tss);
|
||||
|
||||
torture_setup_socket_dir((void **)&s);
|
||||
assert_non_null(s->socket_dir);
|
||||
|
||||
/* Set the default interface for the server */
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
|
||||
setenv("PAM_WRAPPER", "1", 1);
|
||||
|
||||
snprintf(sshd_path,
|
||||
sizeof(sshd_path),
|
||||
"%s/sshd",
|
||||
s->socket_dir);
|
||||
|
||||
rc = mkdir(sshd_path, 0755);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
snprintf(ed25519_hostkey,
|
||||
sizeof(ed25519_hostkey),
|
||||
"%s/sshd/ssh_host_ed25519_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(ed25519_hostkey,
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0));
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
snprintf(dsa_hostkey,
|
||||
sizeof(dsa_hostkey),
|
||||
"%s/sshd/ssh_host_dsa_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(dsa_hostkey, torture_get_testkey(SSH_KEYTYPE_DSS, 0));
|
||||
#endif /* HAVE_DSA */
|
||||
|
||||
snprintf(rsa_hostkey,
|
||||
sizeof(rsa_hostkey),
|
||||
"%s/sshd/ssh_host_rsa_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0));
|
||||
|
||||
snprintf(ecdsa_hostkey,
|
||||
sizeof(ecdsa_hostkey),
|
||||
"%s/sshd/ssh_host_ecdsa_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(ecdsa_hostkey,
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0));
|
||||
|
||||
/* Create default server state */
|
||||
ss = (struct server_state_st *)calloc(1, sizeof(struct server_state_st));
|
||||
assert_non_null(ss);
|
||||
|
||||
ss->address = strdup("127.0.0.10");
|
||||
assert_non_null(ss->address);
|
||||
|
||||
ss->port = 22;
|
||||
|
||||
ss->ecdsa_key = strdup(ecdsa_hostkey);
|
||||
assert_non_null(ss->ecdsa_key);
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
ss->dsa_key = strdup(dsa_hostkey);
|
||||
assert_non_null(ss->dsa_key);
|
||||
#endif /* HAVE_DSA */
|
||||
|
||||
ss->ed25519_key = strdup(ed25519_hostkey);
|
||||
assert_non_null(ed25519_hostkey);
|
||||
|
||||
ss->rsa_key = strdup(rsa_hostkey);
|
||||
assert_non_null(ss->rsa_key);
|
||||
|
||||
ss->host_key = NULL;
|
||||
|
||||
/* Use default username and password (set in default_handle_session_cb) */
|
||||
ss->expected_username = NULL;
|
||||
ss->expected_password = NULL;
|
||||
|
||||
ss->verbosity = torture_libssh_verbosity();
|
||||
|
||||
ss->auth_methods = SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY;
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
ss->with_pcap = 1;
|
||||
ss->pcap_file = strdup(s->pcap_file);
|
||||
assert_non_null(ss->pcap_file);
|
||||
#endif
|
||||
|
||||
/* TODO make configurable */
|
||||
ss->max_tries = 3;
|
||||
ss->error = 0;
|
||||
|
||||
/* Use the default session handling function */
|
||||
ss->handle_session = sftp_handle_session_cb;
|
||||
assert_non_null(ss->handle_session);
|
||||
|
||||
/* Do not use global configuration */
|
||||
ss->parse_global_config = false;
|
||||
|
||||
/* Start the server using the default values */
|
||||
pid = fork_run_server(ss);
|
||||
if (pid < 0) {
|
||||
fail();
|
||||
}
|
||||
|
||||
snprintf(pid_str, sizeof(pid_str), "%d", pid);
|
||||
|
||||
torture_write_file(s->srv_pidfile, (const char *)pid_str);
|
||||
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1);
|
||||
unsetenv("PAM_WRAPPER");
|
||||
|
||||
/* Wait until the sshd is ready to accept connections */
|
||||
//rc = torture_wait_for_daemon(5);
|
||||
//assert_int_equal(rc, 0);
|
||||
|
||||
/* TODO properly wait for the server (use ping approach) */
|
||||
/* Wait 200ms */
|
||||
usleep(200 * 1000);
|
||||
|
||||
tss->state = s;
|
||||
tss->ss = ss;
|
||||
|
||||
*state = tss;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown_default_server(void **state)
|
||||
{
|
||||
struct torture_state *s;
|
||||
struct server_state_st *ss;
|
||||
struct test_server_st *tss;
|
||||
|
||||
tss = *state;
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
ss = tss->ss;
|
||||
assert_non_null(ss);
|
||||
|
||||
/* This function can be reused */
|
||||
torture_teardown_sshd_server((void **)&s);
|
||||
|
||||
free_server_state(tss->ss);
|
||||
SAFE_FREE(tss->ss);
|
||||
SAFE_FREE(tss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_setup(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s;
|
||||
int verbosity = torture_libssh_verbosity();
|
||||
char *cwd = NULL;
|
||||
char *tmp_dir = NULL;
|
||||
bool b = false;
|
||||
int rc;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
/* Make sure we do not test the agent */
|
||||
unsetenv("SSH_AUTH_SOCK");
|
||||
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tmp_dir = torture_make_temp_dir(template);
|
||||
assert_non_null(tmp_dir);
|
||||
|
||||
tss->cwd = cwd;
|
||||
tss->temp_dir = tmp_dir;
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
s->ssh.session = ssh_new();
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
s->ssh.tsftp = (struct torture_sftp*)calloc(1, sizeof(struct torture_sftp));
|
||||
assert_non_null(s->ssh.tsftp);
|
||||
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
/* Make sure no other configuration options from system will get used */
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_teardown(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s;
|
||||
int rc = 0;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
sftp_free(s->ssh.tsftp->sftp);
|
||||
SAFE_FREE(s->ssh.tsftp);
|
||||
|
||||
ssh_disconnect(s->ssh.session);
|
||||
ssh_free(s->ssh.session);
|
||||
|
||||
rc = torture_change_dir(tss->cwd);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = torture_rmdirs(tss->temp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
SAFE_FREE(tss->temp_dir);
|
||||
SAFE_FREE(tss->cwd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_server_establish_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);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
session = s->ssh.session;
|
||||
assert_non_null(session);
|
||||
|
||||
/* TODO: implement proper pam authentication in callback */
|
||||
/* Using the default user for the server */
|
||||
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);
|
||||
|
||||
/* TODO: implement proper pam authentication in callback */
|
||||
/* Using the default password for the server */
|
||||
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;
|
||||
sftp = tsftp->sftp;
|
||||
|
||||
printf("in establish before sftp_new\n");
|
||||
sftp = sftp_new(session);
|
||||
assert_non_null(sftp);
|
||||
|
||||
rc = sftp_init(sftp);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
|
||||
|
||||
static void torture_server_test_sftp_function(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s;
|
||||
struct torture_sftp *tsftp;
|
||||
ssh_session session;
|
||||
sftp_session sftp;
|
||||
int rc;
|
||||
char *rv_str;
|
||||
sftp_dir dir;
|
||||
|
||||
char data[65535] = {0};
|
||||
sftp_file fichier;
|
||||
sftp_file to;
|
||||
int read_len;
|
||||
int write_len;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
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);
|
||||
|
||||
/* TODO: implement proper pam authentication in callback */
|
||||
/* Using the default password for the server */
|
||||
rc = ssh_userauth_password(session, NULL, SSHD_DEFAULT_PASSWORD);
|
||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||
|
||||
rv_str = ssh_get_issue_banner(session);
|
||||
|
||||
/* init sftp session */
|
||||
tsftp = s->ssh.tsftp;
|
||||
sftp = tsftp->sftp;
|
||||
sftp = sftp_new(session);
|
||||
assert_non_null(sftp);
|
||||
|
||||
rc = sftp_init(sftp);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
/* symbol link */
|
||||
rc = sftp_symlink(sftp, "/tmp/this_is_the_link", "/tmp/sftp_symlink_test");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
rv_str = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||
assert_non_null(rv_str);
|
||||
|
||||
rc = sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
/* open and close dir */
|
||||
dir = sftp_opendir(sftp, "./");
|
||||
assert_non_null(dir);
|
||||
|
||||
rc = sftp_closedir(dir);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
/* file read and write */
|
||||
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
||||
assert_non_null(fichier);
|
||||
|
||||
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
|
||||
assert_non_null(to);
|
||||
|
||||
read_len = sftp_read(fichier, data, 4096);
|
||||
write_len = sftp_write(to, data, read_len);
|
||||
assert_int_equal(write_len, read_len);
|
||||
|
||||
rc = sftp_close(fichier);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
rc = sftp_close(to);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
rc = sftp_unlink(sftp, "ssh-copy");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_server_establish_sftp,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_server_test_sftp_function,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests,
|
||||
setup_default_server,
|
||||
teardown_default_server);
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2018 by Red Hat, Inc.
|
||||
*
|
||||
* Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define LIBSSH_STATIC
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "torture.h"
|
||||
#include "torture_key.h"
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#include "test_server.h"
|
||||
#include "default_cb.h"
|
||||
|
||||
#define TORTURE_KNOWN_HOSTS_FILE "libssh_torture_knownhosts"
|
||||
|
||||
const char template[] = "temp_dir_XXXXXX";
|
||||
|
||||
struct test_server_st {
|
||||
struct torture_state *state;
|
||||
struct server_state_st *ss;
|
||||
char *cwd;
|
||||
char *temp_dir;
|
||||
};
|
||||
|
||||
void sftp_handle_session_cb(ssh_event event,
|
||||
ssh_session session,
|
||||
struct server_state_st *state);
|
||||
|
||||
static int setup_default_server(void **state)
|
||||
{
|
||||
struct torture_state *s;
|
||||
struct server_state_st *ss;
|
||||
struct test_server_st *tss;
|
||||
#ifdef HAVE_DSA
|
||||
char dsa_hostkey[1024];
|
||||
#endif /* HAVE_DSA */
|
||||
|
||||
char ed25519_hostkey[1024] = {0};
|
||||
char rsa_hostkey[1024];
|
||||
char ecdsa_hostkey[1024];
|
||||
//char trusted_ca_pubkey[1024];
|
||||
|
||||
char sshd_path[1024];
|
||||
int rc;
|
||||
|
||||
char pid_str[1024];
|
||||
|
||||
pid_t pid;
|
||||
|
||||
assert_non_null(state);
|
||||
|
||||
tss = (struct test_server_st*)calloc(1, sizeof(struct test_server_st));
|
||||
assert_non_null(tss);
|
||||
|
||||
torture_setup_socket_dir((void **)&s);
|
||||
assert_non_null(s->socket_dir);
|
||||
|
||||
/* Set the default interface for the server */
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "10", 1);
|
||||
setenv("PAM_WRAPPER", "1", 1);
|
||||
|
||||
snprintf(sshd_path,
|
||||
sizeof(sshd_path),
|
||||
"%s/sshd",
|
||||
s->socket_dir);
|
||||
|
||||
rc = mkdir(sshd_path, 0755);
|
||||
assert_return_code(rc, errno);
|
||||
|
||||
snprintf(ed25519_hostkey,
|
||||
sizeof(ed25519_hostkey),
|
||||
"%s/sshd/ssh_host_ed25519_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(ed25519_hostkey,
|
||||
torture_get_openssh_testkey(SSH_KEYTYPE_ED25519, 0));
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
snprintf(dsa_hostkey,
|
||||
sizeof(dsa_hostkey),
|
||||
"%s/sshd/ssh_host_dsa_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(dsa_hostkey, torture_get_testkey(SSH_KEYTYPE_DSS, 0));
|
||||
#endif /* HAVE_DSA */
|
||||
|
||||
snprintf(rsa_hostkey,
|
||||
sizeof(rsa_hostkey),
|
||||
"%s/sshd/ssh_host_rsa_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(rsa_hostkey, torture_get_testkey(SSH_KEYTYPE_RSA, 0));
|
||||
|
||||
snprintf(ecdsa_hostkey,
|
||||
sizeof(ecdsa_hostkey),
|
||||
"%s/sshd/ssh_host_ecdsa_key",
|
||||
s->socket_dir);
|
||||
torture_write_file(ecdsa_hostkey,
|
||||
torture_get_testkey(SSH_KEYTYPE_ECDSA_P521, 0));
|
||||
|
||||
/* Create default server state */
|
||||
ss = (struct server_state_st *)calloc(1, sizeof(struct server_state_st));
|
||||
assert_non_null(ss);
|
||||
|
||||
ss->address = strdup("127.0.0.10");
|
||||
assert_non_null(ss->address);
|
||||
|
||||
ss->port = 22;
|
||||
|
||||
ss->ecdsa_key = strdup(ecdsa_hostkey);
|
||||
assert_non_null(ss->ecdsa_key);
|
||||
|
||||
#ifdef HAVE_DSA
|
||||
ss->dsa_key = strdup(dsa_hostkey);
|
||||
assert_non_null(ss->dsa_key);
|
||||
#endif /* HAVE_DSA */
|
||||
|
||||
ss->ed25519_key = strdup(ed25519_hostkey);
|
||||
assert_non_null(ed25519_hostkey);
|
||||
|
||||
ss->rsa_key = strdup(rsa_hostkey);
|
||||
assert_non_null(ss->rsa_key);
|
||||
|
||||
ss->host_key = NULL;
|
||||
|
||||
/* Use default username and password (set in default_handle_session_cb) */
|
||||
ss->expected_username = NULL;
|
||||
ss->expected_password = NULL;
|
||||
|
||||
ss->verbosity = torture_libssh_verbosity();
|
||||
|
||||
ss->auth_methods = SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY;
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
ss->with_pcap = 1;
|
||||
ss->pcap_file = strdup(s->pcap_file);
|
||||
assert_non_null(ss->pcap_file);
|
||||
#endif
|
||||
|
||||
/* TODO make configurable */
|
||||
ss->max_tries = 3;
|
||||
ss->error = 0;
|
||||
|
||||
/* Use the default session handling function */
|
||||
ss->handle_session = sftp_handle_session_cb;
|
||||
assert_non_null(ss->handle_session);
|
||||
|
||||
/* Do not use global configuration */
|
||||
ss->parse_global_config = false;
|
||||
|
||||
/* Start the server using the default values */
|
||||
pid = fork_run_server(ss);
|
||||
if (pid < 0) {
|
||||
fail();
|
||||
}
|
||||
|
||||
snprintf(pid_str, sizeof(pid_str), "%d", pid);
|
||||
|
||||
torture_write_file(s->srv_pidfile, (const char *)pid_str);
|
||||
|
||||
setenv("SOCKET_WRAPPER_DEFAULT_IFACE", "21", 1);
|
||||
unsetenv("PAM_WRAPPER");
|
||||
|
||||
/* Wait until the sshd is ready to accept connections */
|
||||
//rc = torture_wait_for_daemon(5);
|
||||
//assert_int_equal(rc, 0);
|
||||
|
||||
/* TODO properly wait for the server (use ping approach) */
|
||||
/* Wait 200ms */
|
||||
usleep(200 * 1000);
|
||||
|
||||
tss->state = s;
|
||||
tss->ss = ss;
|
||||
|
||||
*state = tss;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int teardown_default_server(void **state)
|
||||
{
|
||||
struct torture_state *s;
|
||||
struct server_state_st *ss;
|
||||
struct test_server_st *tss;
|
||||
|
||||
tss = *state;
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
ss = tss->ss;
|
||||
assert_non_null(ss);
|
||||
|
||||
/* This function can be reused */
|
||||
torture_teardown_sshd_server((void **)&s);
|
||||
|
||||
free_server_state(tss->ss);
|
||||
SAFE_FREE(tss->ss);
|
||||
SAFE_FREE(tss);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_setup(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s;
|
||||
int verbosity = torture_libssh_verbosity();
|
||||
char *cwd = NULL;
|
||||
char *tmp_dir = NULL;
|
||||
bool b = false;
|
||||
int rc;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
/* Make sure we do not test the agent */
|
||||
unsetenv("SSH_AUTH_SOCK");
|
||||
|
||||
cwd = torture_get_current_working_dir();
|
||||
assert_non_null(cwd);
|
||||
|
||||
tmp_dir = torture_make_temp_dir(template);
|
||||
assert_non_null(tmp_dir);
|
||||
|
||||
tss->cwd = cwd;
|
||||
tss->temp_dir = tmp_dir;
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
s->ssh.session = ssh_new();
|
||||
assert_non_null(s->ssh.session);
|
||||
|
||||
s->ssh.tsftp = (struct torture_sftp*)calloc(1, sizeof(struct torture_sftp));
|
||||
assert_non_null(s->ssh.tsftp);
|
||||
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
/* Make sure no other configuration options from system will get used */
|
||||
rc = ssh_options_set(s->ssh.session, SSH_OPTIONS_PROCESS_CONFIG, &b);
|
||||
assert_ssh_return_code(s->ssh.session, rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_teardown(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s;
|
||||
int rc = 0;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
sftp_free(s->ssh.tsftp->sftp);
|
||||
SAFE_FREE(s->ssh.tsftp);
|
||||
|
||||
ssh_disconnect(s->ssh.session);
|
||||
ssh_free(s->ssh.session);
|
||||
|
||||
rc = torture_change_dir(tss->cwd);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
rc = torture_rmdirs(tss->temp_dir);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
SAFE_FREE(tss->temp_dir);
|
||||
SAFE_FREE(tss->cwd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void torture_server_establish_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);
|
||||
|
||||
s = tss->state;
|
||||
assert_non_null(s);
|
||||
|
||||
session = s->ssh.session;
|
||||
assert_non_null(session);
|
||||
|
||||
/* TODO: implement proper pam authentication in callback */
|
||||
/* Using the default user for the server */
|
||||
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);
|
||||
|
||||
/* TODO: implement proper pam authentication in callback */
|
||||
/* Using the default password for the server */
|
||||
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;
|
||||
sftp = tsftp->sftp;
|
||||
|
||||
printf("in establish before sftp_new\n");
|
||||
sftp = sftp_new(session);
|
||||
assert_non_null(sftp);
|
||||
|
||||
rc = sftp_init(sftp);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
|
||||
|
||||
static void torture_server_test_sftp_function(void **state)
|
||||
{
|
||||
struct test_server_st *tss = *state;
|
||||
struct torture_state *s;
|
||||
struct torture_sftp *tsftp;
|
||||
ssh_session session;
|
||||
sftp_session sftp;
|
||||
int rc;
|
||||
char *rv_str;
|
||||
sftp_dir dir;
|
||||
|
||||
char data[65535] = {0};
|
||||
sftp_file fichier;
|
||||
sftp_file to;
|
||||
int read_len;
|
||||
int write_len;
|
||||
|
||||
assert_non_null(tss);
|
||||
|
||||
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);
|
||||
|
||||
/* TODO: implement proper pam authentication in callback */
|
||||
/* Using the default password for the server */
|
||||
rc = ssh_userauth_password(session, NULL, SSHD_DEFAULT_PASSWORD);
|
||||
assert_int_equal(rc, SSH_AUTH_SUCCESS);
|
||||
|
||||
rv_str = ssh_get_issue_banner(session);
|
||||
|
||||
/* init sftp session */
|
||||
tsftp = s->ssh.tsftp;
|
||||
sftp = tsftp->sftp;
|
||||
sftp = sftp_new(session);
|
||||
assert_non_null(sftp);
|
||||
|
||||
rc = sftp_init(sftp);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
/* symbol link */
|
||||
rc = sftp_symlink(sftp, "/tmp/this_is_the_link", "/tmp/sftp_symlink_test");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
rv_str = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||
assert_non_null(rv_str);
|
||||
|
||||
rc = sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
/* open and close dir */
|
||||
dir = sftp_opendir(sftp, "./");
|
||||
assert_non_null(dir);
|
||||
|
||||
rc = sftp_closedir(dir);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
/* file read and write */
|
||||
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
||||
assert_non_null(fichier);
|
||||
|
||||
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
|
||||
assert_non_null(to);
|
||||
|
||||
read_len = sftp_read(fichier, data, 4096);
|
||||
write_len = sftp_write(to, data, read_len);
|
||||
assert_int_equal(write_len, read_len);
|
||||
|
||||
rc = sftp_close(fichier);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
rc = sftp_close(to);
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
|
||||
rc = sftp_unlink(sftp, "ssh-copy");
|
||||
assert_int_equal(rc, SSH_OK);
|
||||
}
|
||||
|
||||
int torture_run_tests(void) {
|
||||
int rc;
|
||||
struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(torture_server_establish_sftp,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
cmocka_unit_test_setup_teardown(torture_server_test_sftp_function,
|
||||
session_setup,
|
||||
session_teardown),
|
||||
};
|
||||
|
||||
ssh_init();
|
||||
|
||||
torture_filter_tests(tests);
|
||||
rc = cmocka_run_group_tests(tests,
|
||||
setup_default_server,
|
||||
teardown_default_server);
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
Reference in New Issue
Block a user