From a8efffa96963e47ca604b251b09cc23999ac512c Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Fri, 16 Jul 2010 23:14:47 +0200 Subject: [PATCH] New example for port forwarding Conflicts: examples/CMakeLists.txt --- examples/CMakeLists.txt | 3 + examples/sshnetcat.c | 247 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 examples/sshnetcat.c diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b912df56..867869c8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable(scp_download scp_download.c ${examples_SRCS}) add_executable(samplessh sample.c ${examples_SRCS}) add_executable(exec exec.c ${examples_SRCS}) add_executable(senddata senddata.c ${examples_SRCS}) +add_executable(sshnetcat sshnetcat.c ${examples_SRCS}) add_executable(libsshpp libsshpp.cpp) @@ -25,6 +26,8 @@ target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY}) target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY}) target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY}) target_link_libraries(libsshpp ${LIBSSH_SHARED_LIBRARY}) +target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY}) + include_directories( ${LIBSSH_PUBLIC_INCLUDE_DIRS} diff --git a/examples/sshnetcat.c b/examples/sshnetcat.c new file mode 100644 index 00000000..21b92425 --- /dev/null +++ b/examples/sshnetcat.c @@ -0,0 +1,247 @@ +/* +Copyright 2010 Aris Adamantiadis + +This file is part of the SSH Library + +You are free to copy this file, modify it in any way, consider it being public +domain. This does not apply to the rest of the library though, but it is +allowed to cut-and-paste working code from this file to any license of +program. +The goal is to show the API in action. It's not a reference on how terminal +clients must be made or how a client should react. +*/ + +#include "config.h" +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "examples_common.h" +char *host; +const char *desthost="localhost"; +const char *port="22"; + +#ifdef WITH_PCAP +#include +char *pcap_file=NULL; +#endif + +static void usage(){ + fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n"); + exit(1); +} + +static int opts(int argc, char **argv){ + int i; + while((i=getopt(argc,argv,"P:"))!=-1){ + switch(i){ +#ifdef WITH_PCAP + case 'P': + pcap_file=optarg; + break; +#endif + default: + fprintf(stderr,"unknown option %c\n",optopt); + usage(); + } + } + if(optind < argc) + host=argv[optind++]; + if(optind < argc) + desthost=argv[optind++]; + if(optind < argc) + port=argv[optind++]; + if(host==NULL) + usage(); + return 0; +} + +static void select_loop(ssh_session session,ssh_channel channel){ + fd_set fds; + struct timeval timeout; + char buffer[4096]; + /* channels will be set to the channels to poll. + * outchannels will contain the result of the poll + */ + ssh_channel channels[2], outchannels[2]; + int lus; + int eof=0; + int maxfd; + int ret; + while(channel){ + do{ + FD_ZERO(&fds); + if(!eof) + FD_SET(0,&fds); + timeout.tv_sec=30; + timeout.tv_usec=0; + FD_SET(ssh_get_fd(session),&fds); + maxfd=ssh_get_fd(session)+1; + channels[0]=channel; // set the first channel we want to read from + channels[1]=NULL; + ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout); + if(ret==EINTR) + continue; + if(FD_ISSET(0,&fds)){ + lus=read(0,buffer,sizeof(buffer)); + if(lus) + channel_write(channel,buffer,lus); + else { + eof=1; + channel_send_eof(channel); + } + } + if(channel && channel_is_closed(channel)){ + ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel)); + + channel_free(channel); + channel=NULL; + channels[0]=NULL; + } + if(outchannels[0]){ + while(channel && channel_is_open(channel) && channel_poll(channel,0)){ + lus=channel_read(channel,buffer,sizeof(buffer),0); + if(lus==-1){ + fprintf(stderr, "Error reading channel: %s\n", + ssh_get_error(session)); + return; + } + if(lus==0){ + ssh_log(session,SSH_LOG_RARE,"EOF received\n"); + ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel)); + + channel_free(channel); + channel=channels[0]=NULL; + } else + write(1,buffer,lus); + } + while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */ + lus=channel_read(channel,buffer,sizeof(buffer),1); + if(lus==-1){ + fprintf(stderr, "Error reading channel: %s\n", + ssh_get_error(session)); + return; + } + if(lus==0){ + ssh_log(session,SSH_LOG_RARE,"EOF received\n"); + ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel)); + channel_free(channel); + channel=channels[0]=NULL; + } else + write(2,buffer,lus); + } + } + if(channel && channel_is_closed(channel)){ + channel_free(channel); + channel=NULL; + } + } while (ret==EINTR || ret==SSH_EINTR); + + } +} + +static void forwarding(ssh_session session){ + ssh_channel channel; + int r; + channel=channel_new(session); + r=channel_open_forward(channel,desthost,atoi(port),"localhost",22); + if(r<0) { + printf("error forwarding port : %s\n",ssh_get_error(session)); + return; + } + select_loop(session,channel); +} + +static int client(ssh_session session){ + int auth=0; + char *banner; + int state; + + if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) + return -1; + ssh_options_parse_config(session, NULL); + + if(ssh_connect(session)){ + fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session)); + return -1; + } + state=verify_knownhost(session); + if (state != 0) + return -1; + ssh_userauth_none(session, NULL); + banner=ssh_get_issue_banner(session); + if(banner){ + printf("%s\n",banner); + free(banner); + } + auth=authenticate_console(session); + if(auth != SSH_AUTH_SUCCESS){ + return -1; + } + ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success"); + forwarding(session); + return 0; +} + +#ifdef WITH_PCAP +ssh_pcap_file pcap; +void set_pcap(ssh_session session); +void set_pcap(ssh_session session){ + if(!pcap_file) + return; + pcap=ssh_pcap_file_new(); + if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){ + printf("Error opening pcap file\n"); + ssh_pcap_file_free(pcap); + pcap=NULL; + return; + } + ssh_set_pcap_file(session,pcap); +} + +void cleanup_pcap(void); +void cleanup_pcap(){ + ssh_pcap_file_free(pcap); + pcap=NULL; +} +#endif + +int main(int argc, char **argv){ + ssh_session session; + + session = ssh_new(); + + if(ssh_options_getopt(session, &argc, argv)) { + fprintf(stderr, "error parsing command line :%s\n", + ssh_get_error(session)); + usage(); + } + opts(argc,argv); +#ifdef WITH_PCAP + set_pcap(session); +#endif + client(session); + + ssh_disconnect(session); + ssh_free(session); +#ifdef WITH_PCAP + cleanup_pcap(); +#endif + + ssh_finalize(); + + return 0; +}