diff --git a/src/sftp.c b/src/sftp.c index 398d662c..b0bf1d49 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -266,66 +266,37 @@ error: return NULL; } -int sftp_server_init(sftp_session sftp){ - ssh_session session = sftp->session; - sftp_packet packet = NULL; - ssh_buffer reply = NULL; - uint32_t version; - int rc; +/* FIXME Untested. To be @deprecated */ +int sftp_server_init(sftp_session sftp) +{ + ssh_session session = sftp->session; + sftp_client_message msg = NULL; + int rc; - packet = sftp_packet_read(sftp); - if (packet == NULL) { - return -1; - } + msg = sftp_get_client_message(sftp); + if (msg == NULL) { + return -1; + } - if (packet->type != SSH_FXP_INIT) { - ssh_set_error(session, SSH_FATAL, - "Packet read of type %d instead of SSH_FXP_INIT", - packet->type); + if (msg->type != SSH_FXP_INIT) { + ssh_set_error(session, + SSH_FATAL, + "Packet read of type %d instead of SSH_FXP_INIT", + msg->type); + return -1; + } - return -1; - } + SSH_LOG(SSH_LOG_PACKET, "Received SSH_FXP_INIT"); - SSH_LOG(SSH_LOG_PACKET, "Received SSH_FXP_INIT"); + rc = sftp_process_init_packet(msg); + if (rc != SSH_OK) { + ssh_set_error(session, + SSH_FATAL, + "Failed to process the SSH_FXP_INIT message"); + return -1; + } - ssh_buffer_get_u32(packet->payload, &version); - version = ntohl(version); - SSH_LOG(SSH_LOG_PACKET, "Client version: %" PRIu32, version); - sftp->client_version = (int)version; - - reply = ssh_buffer_new(); - if (reply == NULL) { - ssh_set_error_oom(session); - return -1; - } - - rc = ssh_buffer_pack(reply, "dssss", - LIBSFTP_VERSION, - "posix-rename@openssh.com", - "1", - "hardlink@openssh.com", - "1"); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - SSH_BUFFER_FREE(reply); - return -1; - } - - if (sftp_packet_write(sftp, SSH_FXP_VERSION, reply) < 0) { - SSH_BUFFER_FREE(reply); - return -1; - } - SSH_BUFFER_FREE(reply); - - SSH_LOG(SSH_LOG_DEBUG, "Server version sent"); - - if (version > LIBSFTP_VERSION) { - sftp->version = LIBSFTP_VERSION; - } else { - sftp->version = (int)version; - } - - return 0; + return 0; } void sftp_server_free(sftp_session sftp) @@ -354,53 +325,6 @@ void sftp_server_free(sftp_session sftp) SAFE_FREE(sftp); } -int sftp_process_init_packet(sftp_client_message client_msg) -{ - sftp_session sftp = client_msg->sftp; - ssh_session session = sftp->session; - int version; - ssh_buffer reply; - int rc; - - version = sftp->client_version; - reply = ssh_buffer_new(); - if (reply == NULL) { - ssh_set_error_oom(session); - return -1; - } - - rc = ssh_buffer_pack(reply, "dssssss", - LIBSFTP_VERSION, - "posix-rename@openssh.com", - "1", - "hardlink@openssh.com", - "1", - "statvfs@openssh.com", - "2"); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - SSH_BUFFER_FREE(reply); - return -1; - } - - rc = sftp_packet_write(sftp, SSH_FXP_VERSION, reply); - if (rc < 0) { - SSH_BUFFER_FREE(reply); - return -1; - } - SSH_BUFFER_FREE(reply); - - SSH_LOG(SSH_LOG_PROTOCOL, "Server version sent"); - - if (version > LIBSFTP_VERSION) { - sftp->version = LIBSFTP_VERSION; - } else { - sftp->version = version; - } - - return SSH_OK; -} - #endif /* WITH_SERVER */ void sftp_free(sftp_session sftp) @@ -2851,7 +2775,8 @@ int sftp_utimes(sftp_session sftp, const char *file, return sftp_setstat(sftp, file, &attr); } -int sftp_symlink(sftp_session sftp, const char *target, const char *dest) { +int sftp_symlink(sftp_session sftp, const char *target, const char *dest) +{ sftp_status_message status = NULL; sftp_message msg = NULL; ssh_buffer buffer; diff --git a/src/sftpserver.c b/src/sftpserver.c index f50545fe..29c5d032 100644 --- a/src/sftpserver.c +++ b/src/sftpserver.c @@ -40,219 +40,10 @@ #define SFTP_HANDLES 256 -sftp_client_message sftp_get_client_message(sftp_session sftp) { - ssh_session session = sftp->session; - sftp_packet packet; - sftp_client_message msg; - ssh_buffer payload; - int rc; - - msg = malloc(sizeof (struct sftp_client_message_struct)); - if (msg == NULL) { - ssh_set_error_oom(session); - return NULL; - } - ZERO_STRUCTP(msg); - - packet = sftp_packet_read(sftp); - if (packet == NULL) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - - payload = packet->payload; - msg->type = packet->type; - msg->sftp = 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; - } - - 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; - } - - ssh_buffer_get_u32(payload, &msg->id); - - switch(msg->type) { - 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; - } - break; - case SSH_FXP_READ: - rc = ssh_buffer_unpack(payload, - "Sqd", - &msg->handle, - &msg->offset, - &msg->len); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - break; - case SSH_FXP_WRITE: - rc = ssh_buffer_unpack(payload, - "SqS", - &msg->handle, - &msg->offset, - &msg->data); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - break; - case SSH_FXP_REMOVE: - case SSH_FXP_RMDIR: - case SSH_FXP_OPENDIR: - case SSH_FXP_READLINK: - case SSH_FXP_REALPATH: - rc = ssh_buffer_unpack(payload, - "s", - &msg->filename); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - break; - case SSH_FXP_RENAME: - case SSH_FXP_SYMLINK: - rc = ssh_buffer_unpack(payload, - "sS", - &msg->filename, - &msg->data); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - break; - case SSH_FXP_MKDIR: - case SSH_FXP_SETSTAT: - rc = ssh_buffer_unpack(payload, - "s", - &msg->filename); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - msg->attr = sftp_parse_attr(sftp, payload, 0); - if (msg->attr == NULL) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - 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; - } - msg->attr = sftp_parse_attr(sftp, payload, 0); - if (msg->attr == NULL) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - break; - case SSH_FXP_LSTAT: - case SSH_FXP_STAT: - rc = ssh_buffer_unpack(payload, - "s", - &msg->filename); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - if(sftp->version > 3) { - ssh_buffer_unpack(payload, "d", &msg->flags); - } - break; - case SSH_FXP_OPEN: - rc = ssh_buffer_unpack(payload, - "sd", - &msg->filename, - &msg->flags); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - msg->attr = sftp_parse_attr(sftp, payload, 0); - if (msg->attr == NULL) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - break; - case SSH_FXP_FSTAT: - rc = ssh_buffer_unpack(payload, - "S", - &msg->handle); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - break; - case SSH_FXP_EXTENDED: - rc = ssh_buffer_unpack(payload, - "s", - &msg->submessage); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - - if (strcmp(msg->submessage, "hardlink@openssh.com") == 0 || - strcmp(msg->submessage, "posix-rename@openssh.com") == 0) { - rc = ssh_buffer_unpack(payload, - "sS", - &msg->filename, - &msg->data); - if (rc != SSH_OK) { - ssh_set_error_oom(session); - sftp_client_message_free(msg); - return NULL; - } - } - break; - default: - ssh_set_error(sftp->session, SSH_FATAL, - "Received unhandled sftp message %d", msg->type); - sftp_client_message_free(msg); - return NULL; - } - - return msg; -} - -sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp) +static sftp_client_message +sftp_make_client_message(sftp_session sftp, sftp_packet packet) { ssh_session session = sftp->session; - sftp_packet packet; sftp_client_message msg; ssh_buffer payload; int rc; @@ -264,11 +55,6 @@ sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp) return NULL; } - packet = sftp->read_packet; - if (packet == NULL) { - goto error; - } - payload = packet->payload; msg->type = packet->type; msg->sftp = sftp; @@ -448,6 +234,29 @@ error: return NULL; } +sftp_client_message sftp_get_client_message(sftp_session sftp) +{ + ssh_session session = sftp->session; + sftp_packet packet; + + packet = sftp_packet_read(sftp); + if (packet == NULL) { + ssh_set_error_oom(session); + return NULL; + } + return sftp_make_client_message(sftp, packet); +} + +sftp_client_message sftp_get_client_message_from_packet(sftp_session sftp) +{ + sftp_packet packet = NULL; + + packet = sftp->read_packet; + if (packet == NULL) { + return NULL; + } + return sftp_make_client_message(sftp, packet); +} /* Send an sftp client message. Can be used in cas of proxying */ int sftp_send_client_message(sftp_session sftp, sftp_client_message msg){ @@ -714,6 +523,53 @@ int sftp_reply_statvfs(sftp_client_message msg, sftp_statvfs_t st) return ret; } +int sftp_process_init_packet(sftp_client_message client_msg) +{ + sftp_session sftp = client_msg->sftp; + ssh_session session = sftp->session; + int version; + ssh_buffer reply; + int rc; + + version = sftp->client_version; + reply = ssh_buffer_new(); + if (reply == NULL) { + ssh_set_error_oom(session); + return -1; + } + + rc = ssh_buffer_pack(reply, "dssssss", + LIBSFTP_VERSION, + "posix-rename@openssh.com", + "1", + "hardlink@openssh.com", + "1", + "statvfs@openssh.com", + "2"); + if (rc != SSH_OK) { + ssh_set_error_oom(session); + SSH_BUFFER_FREE(reply); + return -1; + } + + rc = sftp_packet_write(sftp, SSH_FXP_VERSION, reply); + if (rc < 0) { + SSH_BUFFER_FREE(reply); + return -1; + } + SSH_BUFFER_FREE(reply); + + SSH_LOG(SSH_LOG_PROTOCOL, "Server version sent"); + + if (version > LIBSFTP_VERSION) { + sftp->version = LIBSFTP_VERSION; + } else { + sftp->version = version; + } + + return SSH_OK; +} + /* * This function will return you a new handle to give the client.