diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2010-05-10 22:32:52 +0200 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2010-05-10 22:32:52 +0200 |
commit | bae409071522ae65c02bc36fccb87ee2a7179edf (patch) | |
tree | 0481d1b62e6281b8de5b15ea78dd76ce0a681c9b | |
parent | 403ded1e978f716769ade6d099b2419e4fceaff7 (diff) | |
download | libssh-bae409071522ae65c02bc36fccb87ee2a7179edf.tar.gz libssh-bae409071522ae65c02bc36fccb87ee2a7179edf.tar.xz libssh-bae409071522ae65c02bc36fccb87ee2a7179edf.zip |
Backport of the proxycommand feature
-rw-r--r-- | include/libssh/libssh.h | 3 | ||||
-rw-r--r-- | include/libssh/session.h | 1 | ||||
-rw-r--r-- | include/libssh/socket.h | 6 | ||||
-rw-r--r-- | libssh/client.c | 7 | ||||
-rw-r--r-- | libssh/config.c | 10 | ||||
-rw-r--r-- | libssh/options.c | 12 | ||||
-rw-r--r-- | libssh/session.c | 1 | ||||
-rw-r--r-- | libssh/socket.c | 50 |
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: */ |