From ed660c29c348eb2f7f2af21fa562589561cb35f1 Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Wed, 29 Jul 2009 16:05:45 +0200 Subject: [PATCH] Check for OpenSSH and implement sftp_symlink correct. When OpenSSH's sftp-server was implemented, the order of the arguments to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, the reversal was not noticed until the server was widely deployed. Since fixing this to follow the specification would cause incompatibility, the current order was retained. --- include/libssh/libssh.h | 1 + include/libssh/priv.h | 1 + libssh/client.c | 34 +++++++++++++++++++++++++++++++++- libssh/sftp.c | 30 ++++++++++++++++++++++++++---- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index 5ed2c670..f4dbe126 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -211,6 +211,7 @@ int ssh_connect(SSH_SESSION *session); void ssh_disconnect(SSH_SESSION *session); int ssh_service_request(SSH_SESSION *session, const char *service); char *ssh_get_issue_banner(SSH_SESSION *session); +int ssh_get_openssh_version(SSH_SESSION *session); /* get copyright informations */ const char *ssh_copyright(void); diff --git a/include/libssh/priv.h b/include/libssh/priv.h index 958b0d04..b01b4e93 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -337,6 +337,7 @@ struct ssh_session { int protoversion; int server; int client; + int openssh; u32 send_seq; u32 recv_seq; /* status flags */ diff --git a/libssh/client.c b/libssh/client.c index 5fdec8ee..2ef5568e 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -98,7 +98,10 @@ char *ssh_get_banner(SSH_SESSION *session) { * @see ssh_get_banner() */ static int ssh_analyze_banner(SSH_SESSION *session, int *ssh1, int *ssh2) { - char *banner = session->serverbanner; + const char *banner = session->serverbanner; + const char *openssh; + + ssh_log(session, SSH_LOG_RARE, "Analyzing banner: %s", banner); if (strncmp(banner, "SSH-", 4) != 0) { ssh_set_error(session, SSH_FATAL, "Protocol mismatch: %s", banner); @@ -129,6 +132,17 @@ static int ssh_analyze_banner(SSH_SESSION *session, int *ssh1, int *ssh2) { return -1; } + openssh = strstr(banner, "OpenSSH"); + if (openssh != NULL) { + int major, minor; + major = strtol(openssh + 8, (char **) NULL, 10); + minor = strtol(openssh + 10, (char **) NULL, 10); + session->openssh = SSH_VERSION_INT(major, minor, 0); + ssh_log(session, SSH_LOG_RARE, + "We are talking to an OpenSSH server version: %d.%d (%x)", + major, minor, session->openssh); + } + return 0; } @@ -620,6 +634,24 @@ char *ssh_get_issue_banner(SSH_SESSION *session) { return string_to_char(session->banner); } +/** + * @brief Get the version of the OpenSSH server, if it is not an OpenSSH server + * then 0 will be returned. + * + * You can use the SSH_VERSION_INT macro to compare version numbers. + * + * @param session The SSH session to use. + * + * @return The version number if available, 0 otherwise. + */ +int ssh_get_openssh_version(SSH_SESSION *session) { + if (session == NULL) { + return 0; + } + + return session->openssh; +} + /** * @brief Disconnect from a session (client or server). * diff --git a/libssh/sftp.c b/libssh/sftp.c index e86a262b..f720aa58 100644 --- a/libssh/sftp.c +++ b/libssh/sftp.c @@ -2243,10 +2243,32 @@ int sftp_symlink(SFTP_SESSION *sftp, const char *target, const char *dest) { } id = sftp_get_new_id(sftp); - if (buffer_add_u32(buffer, id) < 0 || - buffer_add_ssh_string(buffer, target_s) < 0 || - buffer_add_ssh_string(buffer, dest_s) < 0 || - sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) { + if (buffer_add_u32(buffer, id) < 0) { + buffer_free(buffer); + string_free(dest_s); + string_free(target_s); + return -1; + } + if (ssh_get_openssh_version(sftp->session)) { + /* TODO check for version number if they ever fix it. */ + if (buffer_add_ssh_string(buffer, target_s) < 0 || + buffer_add_ssh_string(buffer, dest_s) < 0) { + buffer_free(buffer); + string_free(dest_s); + string_free(target_s); + return -1; + } + } else { + if (buffer_add_ssh_string(buffer, dest_s) < 0 || + buffer_add_ssh_string(buffer, target_s) < 0) { + buffer_free(buffer); + string_free(dest_s); + string_free(target_s); + return -1; + } + } + + if (sftp_packet_write(sftp, SSH_FXP_SYMLINK, buffer) < 0) { buffer_free(buffer); string_free(dest_s); string_free(target_s);