diff options
Diffstat (limited to 'libssh2-sys/libssh2-1.5.0/example/direct_tcpip.c')
-rw-r--r-- | libssh2-sys/libssh2-1.5.0/example/direct_tcpip.c | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/libssh2-sys/libssh2-1.5.0/example/direct_tcpip.c b/libssh2-sys/libssh2-1.5.0/example/direct_tcpip.c new file mode 100644 index 0000000..49a3737 --- /dev/null +++ b/libssh2-sys/libssh2-1.5.0/example/direct_tcpip.c @@ -0,0 +1,331 @@ +#include "libssh2_config.h" +#include <libssh2.h> + +#ifdef WIN32 +#include <windows.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/time.h> +#endif + +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE (in_addr_t)-1 +#endif + +const char *keyfile1 = "/home/username/.ssh/id_rsa.pub"; +const char *keyfile2 = "/home/username/.ssh/id_rsa"; +const char *username = "username"; +const char *password = ""; + +const char *server_ip = "127.0.0.1"; + +const char *local_listenip = "127.0.0.1"; +unsigned int local_listenport = 2222; + +const char *remote_desthost = "localhost"; /* resolved by the server */ +unsigned int remote_destport = 22; + +enum { + AUTH_NONE = 0, + AUTH_PASSWORD, + AUTH_PUBLICKEY +}; + +int main(int argc, char *argv[]) +{ + int rc, i, auth = AUTH_NONE; + struct sockaddr_in sin; + socklen_t sinlen; + const char *fingerprint; + char *userauthlist; + LIBSSH2_SESSION *session; + LIBSSH2_CHANNEL *channel = NULL; + const char *shost; + unsigned int sport; + fd_set fds; + struct timeval tv; + ssize_t len, wr; + char buf[16384]; + +#ifdef WIN32 + char sockopt; + SOCKET sock = INVALID_SOCKET; + SOCKET listensock = INVALID_SOCKET, forwardsock = INVALID_SOCKET; + WSADATA wsadata; + int err; + + err = WSAStartup(MAKEWORD(2,0), &wsadata); + if (err != 0) { + fprintf(stderr, "WSAStartup failed with error: %d\n", err); + return 1; + } +#else + int sockopt, sock = -1; + int listensock = -1, forwardsock = -1; +#endif + + if (argc > 1) + server_ip = argv[1]; + if (argc > 2) + username = argv[2]; + if (argc > 3) + password = argv[3]; + if (argc > 4) + local_listenip = argv[4]; + if (argc > 5) + local_listenport = atoi(argv[5]); + if (argc > 6) + remote_desthost = argv[6]; + if (argc > 7) + remote_destport = atoi(argv[7]); + + rc = libssh2_init (0); + if (rc != 0) { + fprintf (stderr, "libssh2 initialization failed (%d)\n", rc); + return 1; + } + + /* Connect to SSH server */ + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +#ifdef WIN32 + if (sock == INVALID_SOCKET) { + fprintf(stderr, "failed to open socket!\n"); + return -1; + } +#else + if (sock == -1) { + perror("socket"); + return -1; + } +#endif + + sin.sin_family = AF_INET; + if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(server_ip))) { + perror("inet_addr"); + return -1; + } + sin.sin_port = htons(22); + if (connect(sock, (struct sockaddr*)(&sin), + sizeof(struct sockaddr_in)) != 0) { + fprintf(stderr, "failed to connect!\n"); + return -1; + } + + /* Create a session instance */ + session = libssh2_session_init(); + if(!session) { + fprintf(stderr, "Could not initialize SSH session!\n"); + return -1; + } + + /* ... start it up. This will trade welcome banners, exchange keys, + * and setup crypto, compression, and MAC layers + */ + rc = libssh2_session_handshake(session, sock); + if(rc) { + fprintf(stderr, "Error when starting up SSH session: %d\n", rc); + return -1; + } + + /* At this point we havn't yet authenticated. The first thing to do + * is check the hostkey's fingerprint against our known hosts Your app + * may have it hard coded, may go to a file, may present it to the + * user, that's your call + */ + fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); + fprintf(stderr, "Fingerprint: "); + for(i = 0; i < 20; i++) + fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]); + fprintf(stderr, "\n"); + + /* check what authentication methods are available */ + userauthlist = libssh2_userauth_list(session, username, strlen(username)); + fprintf(stderr, "Authentication methods: %s\n", userauthlist); + if (strstr(userauthlist, "password")) + auth |= AUTH_PASSWORD; + if (strstr(userauthlist, "publickey")) + auth |= AUTH_PUBLICKEY; + + /* check for options */ + if(argc > 8) { + if ((auth & AUTH_PASSWORD) && !strcasecmp(argv[8], "-p")) + auth = AUTH_PASSWORD; + if ((auth & AUTH_PUBLICKEY) && !strcasecmp(argv[8], "-k")) + auth = AUTH_PUBLICKEY; + } + + if (auth & AUTH_PASSWORD) { + if (libssh2_userauth_password(session, username, password)) { + fprintf(stderr, "Authentication by password failed.\n"); + goto shutdown; + } + } else if (auth & AUTH_PUBLICKEY) { + if (libssh2_userauth_publickey_fromfile(session, username, keyfile1, + keyfile2, password)) { + fprintf(stderr, "\tAuthentication by public key failed!\n"); + goto shutdown; + } + fprintf(stderr, "\tAuthentication by public key succeeded.\n"); + } else { + fprintf(stderr, "No supported authentication methods found!\n"); + goto shutdown; + } + + listensock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +#ifdef WIN32 + if (listensock == INVALID_SOCKET) { + fprintf(stderr, "failed to open listen socket!\n"); + return -1; + } +#else + if (listensock == -1) { + perror("socket"); + return -1; + } +#endif + + sin.sin_family = AF_INET; + sin.sin_port = htons(local_listenport); + if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(local_listenip))) { + perror("inet_addr"); + goto shutdown; + } + sockopt = 1; + setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); + sinlen=sizeof(sin); + if (-1 == bind(listensock, (struct sockaddr *)&sin, sinlen)) { + perror("bind"); + goto shutdown; + } + if (-1 == listen(listensock, 2)) { + perror("listen"); + goto shutdown; + } + + fprintf(stderr, "Waiting for TCP connection on %s:%d...\n", + inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); + + forwardsock = accept(listensock, (struct sockaddr *)&sin, &sinlen); +#ifdef WIN32 + if (forwardsock == INVALID_SOCKET) { + fprintf(stderr, "failed to accept forward socket!\n"); + goto shutdown; + } +#else + if (forwardsock == -1) { + perror("accept"); + goto shutdown; + } +#endif + + shost = inet_ntoa(sin.sin_addr); + sport = ntohs(sin.sin_port); + + fprintf(stderr, "Forwarding connection from %s:%d here to remote %s:%d\n", + shost, sport, remote_desthost, remote_destport); + + channel = libssh2_channel_direct_tcpip_ex(session, remote_desthost, + remote_destport, shost, sport); + if (!channel) { + fprintf(stderr, "Could not open the direct-tcpip channel!\n" + "(Note that this can be a problem at the server!" + " Please review the server logs.)\n"); + goto shutdown; + } + + /* Must use non-blocking IO hereafter due to the current libssh2 API */ + libssh2_session_set_blocking(session, 0); + + while (1) { + FD_ZERO(&fds); + FD_SET(forwardsock, &fds); + tv.tv_sec = 0; + tv.tv_usec = 100000; + rc = select(forwardsock + 1, &fds, NULL, NULL, &tv); + if (-1 == rc) { + perror("select"); + goto shutdown; + } + if (rc && FD_ISSET(forwardsock, &fds)) { + len = recv(forwardsock, buf, sizeof(buf), 0); + if (len < 0) { + perror("read"); + goto shutdown; + } else if (0 == len) { + fprintf(stderr, "The client at %s:%d disconnected!\n", shost, + sport); + goto shutdown; + } + wr = 0; + do { + i = libssh2_channel_write(channel, buf, len); + if (i < 0) { + fprintf(stderr, "libssh2_channel_write: %d\n", i); + goto shutdown; + } + wr += i; + } while(i > 0 && wr < len); + } + while (1) { + len = libssh2_channel_read(channel, buf, sizeof(buf)); + if (LIBSSH2_ERROR_EAGAIN == len) + break; + else if (len < 0) { + fprintf(stderr, "libssh2_channel_read: %d", (int)len); + goto shutdown; + } + wr = 0; + while (wr < len) { + i = send(forwardsock, buf + wr, len - wr, 0); + if (i <= 0) { + perror("write"); + goto shutdown; + } + wr += i; + } + if (libssh2_channel_eof(channel)) { + fprintf(stderr, "The server at %s:%d disconnected!\n", + remote_desthost, remote_destport); + goto shutdown; + } + } + } + +shutdown: +#ifdef WIN32 + closesocket(forwardsock); + closesocket(listensock); +#else + close(forwardsock); + close(listensock); +#endif + if (channel) + libssh2_channel_free(channel); + libssh2_session_disconnect(session, "Client disconnecting normally"); + libssh2_session_free(session); + +#ifdef WIN32 + closesocket(sock); +#else + close(sock); +#endif + + libssh2_exit(); + + return 0; +} |