aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schneider <mail@cynapses.org>2009-07-28 11:47:53 +0200
committerAndreas Schneider <mail@cynapses.org>2009-07-28 13:25:26 +0200
commit69ceaae9a9f69dba11ab01889da5b41cb1487896 (patch)
treef32840e6c682e101107b2be40d64832e9c88da4f
parent1abdb28995fa5db61af7f385abf078c9b58fd843 (diff)
downloadlibssh-69ceaae9a9f69dba11ab01889da5b41cb1487896.tar.gz
libssh-69ceaae9a9f69dba11ab01889da5b41cb1487896.tar.xz
libssh-69ceaae9a9f69dba11ab01889da5b41cb1487896.zip
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.
-rw-r--r--include/libssh/libssh.h1
-rw-r--r--include/libssh/priv.h1
-rw-r--r--libssh/client.c34
-rw-r--r--libssh/sftp.c30
4 files changed, 61 insertions, 5 deletions
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index 161a8f5f..924992a2 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -217,6 +217,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 a5c91cc4..6b1cd3cb 100644
--- a/include/libssh/priv.h
+++ b/include/libssh/priv.h
@@ -340,6 +340,7 @@ struct ssh_session_struct {
int protoversion;
int server;
int client;
+ int openssh;
uint32_t send_seq;
uint32_t recv_seq;
/* status flags */
diff --git a/libssh/client.c b/libssh/client.c
index acccd146..cbc70e31 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;
}
@@ -616,6 +630,24 @@ char *ssh_get_issue_banner(SSH_SESSION *session) {
}
/**
+ * @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).
*
* @param session The SSH session to disconnect.
diff --git a/libssh/sftp.c b/libssh/sftp.c
index f64aa302..41402810 100644
--- a/libssh/sftp.c
+++ b/libssh/sftp.c
@@ -2247,10 +2247,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);