mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-29 01:03:57 +03:00
Add support to read and store sftp extensions.
This commit is contained in:
@@ -58,12 +58,15 @@ extern "C" {
|
|||||||
#endif /* gid_t */
|
#endif /* gid_t */
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
typedef struct sftp_ext_struct *sftp_ext;
|
||||||
|
|
||||||
typedef struct sftp_session_struct {
|
typedef struct sftp_session_struct {
|
||||||
SSH_SESSION *session;
|
SSH_SESSION *session;
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
int server_version;
|
int server_version;
|
||||||
int client_version;
|
int client_version;
|
||||||
int version;
|
int version;
|
||||||
|
struct sftp_ext_struct *ext;
|
||||||
struct request_queue *queue;
|
struct request_queue *queue;
|
||||||
uint32_t id_counter;
|
uint32_t id_counter;
|
||||||
int errnum;
|
int errnum;
|
||||||
|
|||||||
140
libssh/sftp.c
140
libssh/sftp.c
@@ -44,12 +44,55 @@
|
|||||||
#define sftp_enter_function() _enter_function(sftp->channel->session)
|
#define sftp_enter_function() _enter_function(sftp->channel->session)
|
||||||
#define sftp_leave_function() _leave_function(sftp->channel->session)
|
#define sftp_leave_function() _leave_function(sftp->channel->session)
|
||||||
|
|
||||||
|
struct sftp_ext_struct {
|
||||||
|
int rename_openssh;
|
||||||
|
int rename_openssh_version;
|
||||||
|
int statvfs_openssh;
|
||||||
|
int statvfs_openssh_version;
|
||||||
|
int fstatvfs_openssh;
|
||||||
|
int fstatvfs_openssh_version;
|
||||||
|
unsigned int count;
|
||||||
|
char **name;
|
||||||
|
char **data;
|
||||||
|
};
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
static int sftp_enqueue(SFTP_SESSION *session, SFTP_MESSAGE *msg);
|
static int sftp_enqueue(SFTP_SESSION *session, SFTP_MESSAGE *msg);
|
||||||
static void sftp_message_free(SFTP_MESSAGE *msg);
|
static void sftp_message_free(SFTP_MESSAGE *msg);
|
||||||
static void sftp_set_error(SFTP_SESSION *sftp, int errnum);
|
static void sftp_set_error(SFTP_SESSION *sftp, int errnum);
|
||||||
static void status_msg_free(STATUS_MESSAGE *status);
|
static void status_msg_free(STATUS_MESSAGE *status);
|
||||||
|
|
||||||
|
static sftp_ext sftp_ext_new(void) {
|
||||||
|
sftp_ext ext;
|
||||||
|
|
||||||
|
ext = malloc(sizeof(struct sftp_ext_struct));
|
||||||
|
if (ext == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ZERO_STRUCTP(ext);
|
||||||
|
|
||||||
|
return ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sftp_ext_free(sftp_ext ext) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (ext == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext->count) {
|
||||||
|
for (i = 0; i < ext->count; i++) {
|
||||||
|
SAFE_FREE(ext->name[i]);
|
||||||
|
SAFE_FREE(ext->data[i]);
|
||||||
|
}
|
||||||
|
SAFE_FREE(ext->name);
|
||||||
|
SAFE_FREE(ext->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFE_FREE(ext);
|
||||||
|
}
|
||||||
|
|
||||||
SFTP_SESSION *sftp_new(SSH_SESSION *session){
|
SFTP_SESSION *sftp_new(SSH_SESSION *session){
|
||||||
SFTP_SESSION *sftp;
|
SFTP_SESSION *sftp;
|
||||||
|
|
||||||
@@ -65,7 +108,14 @@ SFTP_SESSION *sftp_new(SSH_SESSION *session){
|
|||||||
leave_function();
|
leave_function();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(sftp,0,sizeof(SFTP_SESSION));
|
ZERO_STRUCTP(sftp);
|
||||||
|
|
||||||
|
sftp->ext = sftp_ext_new();
|
||||||
|
if (sftp->ext == NULL) {
|
||||||
|
SAFE_FREE(sftp);
|
||||||
|
sftp_leave_function();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
sftp->session = session;
|
sftp->session = session;
|
||||||
sftp->channel = channel_new(session);
|
sftp->channel = channel_new(session);
|
||||||
@@ -191,7 +241,8 @@ void sftp_free(SFTP_SESSION *sftp){
|
|||||||
}
|
}
|
||||||
|
|
||||||
channel_free(sftp->channel);
|
channel_free(sftp->channel);
|
||||||
memset(sftp, 0, sizeof(*sftp));
|
sftp_ext_free(sftp->ext);
|
||||||
|
ZERO_STRUCTP(sftp);
|
||||||
|
|
||||||
SAFE_FREE(sftp);
|
SAFE_FREE(sftp);
|
||||||
}
|
}
|
||||||
@@ -455,39 +506,84 @@ int sftp_init(SFTP_SESSION *sftp) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_get_u32(packet->payload,&version);
|
buffer_get_u32(packet->payload, &version);
|
||||||
version = ntohl(version);
|
version = ntohl(version);
|
||||||
|
ssh_log(sftp->session, SSH_LOG_RARE,
|
||||||
|
"SFTP server version %d",
|
||||||
|
version);
|
||||||
|
|
||||||
ext_name_s = buffer_get_ssh_string(packet->payload);
|
ext_name_s = buffer_get_ssh_string(packet->payload);
|
||||||
ext_data_s = buffer_get_ssh_string(packet->payload);
|
while (ext_name_s != NULL) {
|
||||||
if (ext_name_s == NULL || (ext_data_s == NULL)) {
|
int count = sftp->ext->count;
|
||||||
string_free(ext_name_s);
|
char **tmp;
|
||||||
string_free(ext_data_s);
|
|
||||||
ssh_log(sftp->session, SSH_LOG_RARE,
|
ext_data_s = buffer_get_ssh_string(packet->payload);
|
||||||
"SFTP server version %d", version);
|
if (ext_data_s == NULL) {
|
||||||
} else {
|
string_free(ext_name_s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ext_name = string_to_char(ext_name_s);
|
ext_name = string_to_char(ext_name_s);
|
||||||
ext_data = string_to_char(ext_data_s);
|
ext_data = string_to_char(ext_data_s);
|
||||||
|
if (ext_name == NULL || ext_data == NULL) {
|
||||||
if (ext_name != NULL || ext_data != NULL) {
|
SAFE_FREE(ext_name);
|
||||||
ssh_log(sftp->session, SSH_LOG_RARE,
|
SAFE_FREE(ext_data);
|
||||||
"SFTP server version %d (%s,%s)",
|
string_free(ext_name_s);
|
||||||
version, ext_name, ext_data);
|
string_free(ext_data_s);
|
||||||
} else {
|
return -1;
|
||||||
ssh_log(sftp->session, SSH_LOG_RARE,
|
|
||||||
"SFTP server version %d", version);
|
|
||||||
}
|
}
|
||||||
SAFE_FREE(ext_name);
|
ssh_log(sftp->session, SSH_LOG_RARE,
|
||||||
SAFE_FREE(ext_data);
|
"SFTP server extension: %s, version: %s",
|
||||||
|
ext_name, ext_data);
|
||||||
|
|
||||||
|
if (strcmp(ext_name, "posix-rename@openssh.com") == 0) {
|
||||||
|
sftp->ext->rename_openssh = 1;
|
||||||
|
sftp->ext->rename_openssh_version = strtol(ext_data, (char **) NULL, 10);
|
||||||
|
} else if (strcmp(ext_name, "statvfs@openssh.com") == 0) {
|
||||||
|
sftp->ext->statvfs_openssh = 1;
|
||||||
|
sftp->ext->statvfs_openssh_version = strtol(ext_data, (char **) NULL, 10);
|
||||||
|
} else if (strcmp(ext_name, "fstatvfs@openssh.com") == 0) {
|
||||||
|
sftp->ext->fstatvfs_openssh = 1;
|
||||||
|
sftp->ext->fstatvfs_openssh_version = strtol(ext_data, (char **) NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
tmp = realloc(sftp->ext->name, count * sizeof(char *));
|
||||||
|
if (tmp == NULL) {
|
||||||
|
SAFE_FREE(ext_name);
|
||||||
|
SAFE_FREE(ext_data);
|
||||||
|
string_free(ext_name_s);
|
||||||
|
string_free(ext_data_s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmp[count - 1] = ext_name;
|
||||||
|
sftp->ext->name = tmp;
|
||||||
|
|
||||||
|
tmp = realloc(sftp->ext->data, count * sizeof(char *));
|
||||||
|
if (tmp == NULL) {
|
||||||
|
SAFE_FREE(ext_name);
|
||||||
|
SAFE_FREE(ext_data);
|
||||||
|
string_free(ext_name_s);
|
||||||
|
string_free(ext_data_s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
tmp[count - 1] = ext_data;
|
||||||
|
sftp->ext->data = tmp;
|
||||||
|
|
||||||
|
sftp->ext->count = count;
|
||||||
|
|
||||||
|
string_free(ext_name_s);
|
||||||
|
string_free(ext_data_s);
|
||||||
|
|
||||||
|
ext_name_s = buffer_get_ssh_string(packet->payload);
|
||||||
}
|
}
|
||||||
string_free(ext_name_s);
|
|
||||||
string_free(ext_data_s);
|
|
||||||
|
|
||||||
sftp_packet_free(packet);
|
sftp_packet_free(packet);
|
||||||
|
|
||||||
sftp->version = sftp->server_version = version;
|
sftp->version = sftp->server_version = version;
|
||||||
|
|
||||||
sftp_leave_function();
|
sftp_leave_function();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user