aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2010-05-10 22:32:52 +0200
committerAris Adamantiadis <aris@0xbadc0de.be>2010-05-10 22:32:52 +0200
commitbae409071522ae65c02bc36fccb87ee2a7179edf (patch)
tree0481d1b62e6281b8de5b15ea78dd76ce0a681c9b
parent403ded1e978f716769ade6d099b2419e4fceaff7 (diff)
downloadlibssh-bae409071522ae65c02bc36fccb87ee2a7179edf.tar.gz
libssh-bae409071522ae65c02bc36fccb87ee2a7179edf.tar.xz
libssh-bae409071522ae65c02bc36fccb87ee2a7179edf.zip
Backport of the proxycommand feature
-rw-r--r--include/libssh/libssh.h3
-rw-r--r--include/libssh/session.h1
-rw-r--r--include/libssh/socket.h6
-rw-r--r--libssh/client.c7
-rw-r--r--libssh/config.c10
-rw-r--r--libssh/options.c12
-rw-r--r--libssh/session.c1
-rw-r--r--libssh/socket.c50
8 files changed, 87 insertions, 3 deletions
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index 75e7da0e..c25f8e67 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -264,7 +264,8 @@ enum ssh_options_e {
SSH_OPTIONS_CIPHERS_C_S,
SSH_OPTIONS_CIPHERS_S_C,
SSH_OPTIONS_COMPRESSION_C_S,
- SSH_OPTIONS_COMPRESSION_S_C
+ SSH_OPTIONS_COMPRESSION_S_C,
+ SSH_OPTIONS_PROXYCOMMAND
};
enum {
diff --git a/include/libssh/session.h b/include/libssh/session.h
index 9bd97315..e95e2351 100644
--- a/include/libssh/session.h
+++ b/include/libssh/session.h
@@ -114,6 +114,7 @@ struct ssh_session_struct {
socket_t fd;
int ssh2;
int ssh1;
+ char *ProxyCommand;
};
int ssh_handle_packets(ssh_session session);
diff --git a/include/libssh/socket.h b/include/libssh/socket.h
index bb54c7ea..ade755d7 100644
--- a/include/libssh/socket.h
+++ b/include/libssh/socket.h
@@ -52,4 +52,10 @@ int ssh_socket_get_status(struct socket *s);
int ssh_socket_data_available(struct socket *s);
int ssh_socket_data_writable(struct socket *s);
+#ifndef _WIN32
+void ssh_execute_command(const char *command, socket_t in, socket_t out);
+socket_t ssh_socket_connect_proxycommand(ssh_session session,
+ const char *command);
+#endif
+
#endif /* SOCKET_H_ */
diff --git a/libssh/client.c b/libssh/client.c
index 43081726..56267784 100644
--- a/libssh/client.c
+++ b/libssh/client.c
@@ -497,13 +497,18 @@ int ssh_connect(ssh_session session) {
leave_function();
return SSH_ERROR;
}
- if (session->fd == -1 && session->host == NULL) {
+ if (session->fd == -1 && session->host == NULL &&
+ session->ProxyCommand == NULL) {
ssh_set_error(session, SSH_FATAL, "Hostname required");
leave_function();
return SSH_ERROR;
}
if (session->fd != -1) {
fd = session->fd;
+#ifndef _WIN32
+ } else if (session->ProxyCommand != NULL) {
+ fd=ssh_socket_connect_proxycommand(session, session->ProxyCommand);
+#endif
} else {
fd = ssh_connect_host(session, session->host, session->bindaddr,
session->port, session->timeout, session->timeout_usec);
diff --git a/libssh/config.c b/libssh/config.c
index e3a00ca6..1af4c6c7 100644
--- a/libssh/config.c
+++ b/libssh/config.c
@@ -38,7 +38,8 @@ enum ssh_config_opcode_e {
SOC_CIPHERS,
SOC_COMPRESSION,
SOC_TIMEOUT,
- SOC_PROTOCOL
+ SOC_PROTOCOL,
+ SOC_PROXYCOMMAND
};
struct ssh_config_keyword_table_s {
@@ -56,6 +57,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
{ "compression", SOC_COMPRESSION },
{ "connecttimeout", SOC_TIMEOUT },
{ "protocol", SOC_PROTOCOL },
+ { "proxycommand", SOC_PROXYCOMMAND },
{ NULL, SOC_UNSUPPORTED }
};
@@ -274,6 +276,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &i);
}
break;
+ case SOC_PROXYCOMMAND:
+ p = ssh_config_get_str(&s, NULL);
+ if (p && *parsing) {
+ ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, p);
+ }
+ break;
case SOC_UNSUPPORTED:
fprintf(stderr, "Unsupported option: %s, line: %d\n", keyword, count);
break;
diff --git a/libssh/options.c b/libssh/options.c
index dafd72e0..0c881cde 100644
--- a/libssh/options.c
+++ b/libssh/options.c
@@ -362,6 +362,10 @@ char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) {
* Set the compression to use for server to client
* communication (string, "none" or "zlib").
*
+ * - SSH_OPTIONS_PROXYCOMMAND:
+ * Set the command to be executed in order to connect to
+ * server.
+ *
* @param value The value to set. This is a generic pointer and the
* datatype which is used should be set according to the
* type set.
@@ -612,6 +616,14 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
return -1;
}
break;
+ case SSH_OPTIONS_PROXYCOMMAND:
+ if (value == NULL) {
+ ssh_set_error_invalid(session, __FUNCTION__);
+ return -1;
+ } else {
+ session->ProxyCommand = strdup(value);
+ }
+ break;
default:
ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
return -1;
diff --git a/libssh/session.c b/libssh/session.c
index c73a2879..57a3e80f 100644
--- a/libssh/session.c
+++ b/libssh/session.c
@@ -213,6 +213,7 @@ void ssh_free(ssh_session session) {
SAFE_FREE(session->host);
SAFE_FREE(session->sshdir);
SAFE_FREE(session->knownhosts);
+ SAFE_FREE(session->ProxyCommand);
for (i = 0; i < 10; i++) {
if (session->wanted_methods[i]) {
diff --git a/libssh/socket.c b/libssh/socket.c
index 933119f7..3ac91caf 100644
--- a/libssh/socket.c
+++ b/libssh/socket.c
@@ -32,6 +32,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
+extern const char **environ;
#endif
#include "libssh/priv.h"
#include "libssh/socket.h"
@@ -39,6 +40,7 @@
#include "libssh/poll.h"
#include "libssh/session.h"
+
/** \defgroup ssh_socket SSH Sockets
* \addtogroup ssh_socket
* @{
@@ -658,6 +660,54 @@ int ssh_socket_get_status(struct socket *s) {
return r;
}
+#ifndef _WIN32
+/**
+ * @internal
+ * @brief executes a command and redirect input and outputs
+ * @param command command to execute
+ * @param in input file descriptor
+ * @param out output file descriptor
+ */
+void ssh_execute_command(const char *command, socket_t in, socket_t out){
+ const char *args[]={"/bin/sh","-c",command,NULL};
+ /* redirect in and out to stdin, stdout and stderr */
+ dup2(in, 0);
+ dup2(out,1);
+ dup2(out,2);
+ close(in);
+ close(out);
+ execve(args[0],(char * const *)args,(char * const *)environ);
+ exit(1);
+}
+
+/**
+ * @internal
+ * @brief Open a socket on a ProxyCommand
+ * This call will always be nonblocking.
+ * @param s socket to connect.
+ * @param command Command to execute.
+ * @returns SSH_OK socket is being connected.
+ * @returns SSH_ERROR error while executing the command.
+ */
+
+socket_t ssh_socket_connect_proxycommand(ssh_session session,
+ const char *command){
+ socket_t fd[2];
+ int pid;
+ enter_function();
+ socketpair(AF_UNIX,SOCK_STREAM,0,fd);
+ pid = fork();
+ if(pid == 0){
+ ssh_execute_command(command,fd[1],fd[1]);
+ }
+ close(fd[1]);
+ ssh_log(session,SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",fd[0],fd[1]);
+ return fd[0];
+}
+
+#endif /* _WIN32 */
+
+
/** @}
*/
/* vim: set ts=2 sw=2 et cindent: */