Blame examples/sshnetcat.c

Packit Service 31306d
/*
Packit Service 31306d
Copyright 2010 Aris Adamantiadis
Packit Service 31306d
Packit Service 31306d
This file is part of the SSH Library
Packit Service 31306d
Packit Service 31306d
You are free to copy this file, modify it in any way, consider it being public
Packit Service 31306d
domain. This does not apply to the rest of the library though, but it is
Packit Service 31306d
allowed to cut-and-paste working code from this file to any license of
Packit Service 31306d
program.
Packit Service 31306d
The goal is to show the API in action. It's not a reference on how terminal
Packit Service 31306d
clients must be made or how a client should react.
Packit Service 31306d
*/
Packit Service 31306d
Packit Service 31306d
#include "config.h"
Packit Service 31306d
#include <stdio.h>
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
#include <string.h>
Packit Service 31306d
#ifdef HAVE_TERMIOS_H
Packit Service 31306d
#include <termios.h>
Packit Service 31306d
#endif
Packit Service 31306d
#ifdef HAVE_UNISTD_H
Packit Service 31306d
#include <unistd.h>
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#include <sys/select.h>
Packit Service 31306d
#include <sys/time.h>
Packit Service 31306d
Packit Service 31306d
#include <sys/ioctl.h>
Packit Service 31306d
#include <errno.h>
Packit Service 31306d
#include <libssh/callbacks.h>
Packit Service 31306d
#include <libssh/libssh.h>
Packit Service 31306d
#include <libssh/sftp.h>
Packit Service 31306d
Packit Service 31306d
#include <fcntl.h>
Packit Service 31306d
Packit Service 31306d
#include "examples_common.h"
Packit Service 31306d
char *host;
Packit Service 31306d
const char *desthost="localhost";
Packit Service 31306d
const char *port="22";
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_PCAP
Packit Service 31306d
#include <libssh/pcap.h>
Packit Service 31306d
char *pcap_file=NULL;
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
static void usage(void)
Packit Service 31306d
{
Packit Service 31306d
  fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
Packit Service 31306d
  exit(1);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int opts(int argc, char **argv){
Packit Service 31306d
    int i;
Packit Service 31306d
    while((i=getopt(argc,argv,"P:"))!=-1){
Packit Service 31306d
        switch(i){
Packit Service 31306d
#ifdef WITH_PCAP
Packit Service 31306d
        	case 'P':
Packit Service 31306d
        		pcap_file=optarg;
Packit Service 31306d
        		break;
Packit Service 31306d
#endif
Packit Service 31306d
            default:
Packit Service 31306d
                fprintf(stderr,"unknown option %c\n",optopt);
Packit Service 31306d
                usage();
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
    if(optind < argc)
Packit Service 31306d
        host=argv[optind++];
Packit Service 31306d
    if(optind < argc)
Packit Service 31306d
        desthost=argv[optind++];
Packit Service 31306d
    if(optind < argc)
Packit Service 31306d
        port=argv[optind++];
Packit Service 31306d
    if(host==NULL)
Packit Service 31306d
        usage();
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static void select_loop(ssh_session session,ssh_channel channel){
Packit Service 31306d
	fd_set fds;
Packit Service 31306d
	struct timeval timeout;
Packit Service 31306d
	char buffer[4096];
Packit Service 31306d
	/* channels will be set to the channels to poll.
Packit Service 31306d
	 * outchannels will contain the result of the poll
Packit Service 31306d
	 */
Packit Service 31306d
	ssh_channel channels[2], outchannels[2];
Packit Service 31306d
	int lus;
Packit Service 31306d
	int eof=0;
Packit Service 31306d
	int maxfd;
Packit Service 31306d
	int ret;
Packit Service 31306d
	while(channel){
Packit Service 31306d
		do{
Packit Service 31306d
            int fd;
Packit Service 31306d
Packit Service 31306d
            ZERO_STRUCT(fds);
Packit Service 31306d
			FD_ZERO(&fds);
Packit Service 31306d
			if(!eof)
Packit Service 31306d
				FD_SET(0,&fds);
Packit Service 31306d
			timeout.tv_sec=30;
Packit Service 31306d
			timeout.tv_usec=0;
Packit Service 31306d
Packit Service 31306d
            fd = ssh_get_fd(session);
Packit Service 31306d
            if (fd == -1) {
Packit Service 31306d
                fprintf(stderr, "Error getting the session file descriptor: %s\n",
Packit Service 31306d
                                ssh_get_error(session));
Packit Service 31306d
                return;
Packit Service 31306d
            }
Packit Service 31306d
            FD_SET(fd, &fds);
Packit Service 31306d
            maxfd = fd + 1;
Packit Service 31306d
Packit Service 31306d
			channels[0]=channel; // set the first channel we want to read from
Packit Service 31306d
			channels[1]=NULL;
Packit Service 31306d
			ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
Packit Service 31306d
			if(ret==EINTR)
Packit Service 31306d
				continue;
Packit Service 31306d
			if(FD_ISSET(0,&fds)){
Packit Service 31306d
				lus=read(0,buffer,sizeof(buffer));
Packit Service 31306d
				if(lus)
Packit Service 31306d
					ssh_channel_write(channel,buffer,lus);
Packit Service 31306d
				else {
Packit Service 31306d
					eof=1;
Packit Service 31306d
					ssh_channel_send_eof(channel);
Packit Service 31306d
				}
Packit Service 31306d
			}
Packit Service 31306d
			if(channel && ssh_channel_is_closed(channel)){
Packit Service 31306d
				ssh_channel_free(channel);
Packit Service 31306d
				channel=NULL;
Packit Service 31306d
				channels[0]=NULL;
Packit Service 31306d
			}
Packit Service 31306d
			if(outchannels[0]){
Packit Service 31306d
				while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
Packit Service 31306d
					lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
Packit Service 31306d
					if(lus==-1){
Packit Service 31306d
						fprintf(stderr, "Error reading channel: %s\n",
Packit Service 31306d
								ssh_get_error(session));
Packit Service 31306d
						return;
Packit Service 31306d
					}
Packit Service 31306d
					if(lus==0){
Packit Service 31306d
						ssh_channel_free(channel);
Packit Service 31306d
						channel=channels[0]=NULL;
Packit Service 31306d
					} else {
Packit Service 31306d
						ret = write(1, buffer, lus);
Packit Service 31306d
						if (ret < 0) {
Packit Service 31306d
							fprintf(stderr, "Error writing to stdin: %s",
Packit Service 31306d
								strerror(errno));
Packit Service 31306d
							return;
Packit Service 31306d
						}
Packit Service 31306d
					}
Packit Service 31306d
				}
Packit Service 31306d
				while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
Packit Service 31306d
					lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
Packit Service 31306d
					if(lus==-1){
Packit Service 31306d
						fprintf(stderr, "Error reading channel: %s\n",
Packit Service 31306d
								ssh_get_error(session));
Packit Service 31306d
						return;
Packit Service 31306d
					}
Packit Service 31306d
					if(lus==0){
Packit Service 31306d
						ssh_channel_free(channel);
Packit Service 31306d
						channel=channels[0]=NULL;
Packit Service 31306d
					} else {
Packit Service 31306d
						ret = write(2, buffer, lus);
Packit Service 31306d
						if (ret < 0) {
Packit Service 31306d
							fprintf(stderr, "Error writing to stderr: %s",
Packit Service 31306d
								strerror(errno));
Packit Service 31306d
							return;
Packit Service 31306d
						}
Packit Service 31306d
                    }
Packit Service 31306d
				}
Packit Service 31306d
			}
Packit Service 31306d
			if(channel && ssh_channel_is_closed(channel)){
Packit Service 31306d
				ssh_channel_free(channel);
Packit Service 31306d
				channel=NULL;
Packit Service 31306d
			}
Packit Service 31306d
		} while (ret==EINTR || ret==SSH_EINTR);
Packit Service 31306d
Packit Service 31306d
	}
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static void forwarding(ssh_session session){
Packit Service 31306d
    ssh_channel channel;
Packit Service 31306d
    int r;
Packit Service 31306d
    channel = ssh_channel_new(session);
Packit Service 31306d
    r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
Packit Service 31306d
    if(r<0) {
Packit Service 31306d
        printf("error forwarding port : %s\n",ssh_get_error(session));
Packit Service 31306d
        return;
Packit Service 31306d
    }
Packit Service 31306d
    select_loop(session,channel);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int client(ssh_session session){
Packit Service 31306d
  int auth=0;
Packit Service 31306d
  char *banner;
Packit Service 31306d
  int state;
Packit Service 31306d
Packit Service 31306d
  if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
Packit Service 31306d
    return -1;
Packit Service 31306d
  ssh_options_parse_config(session, NULL);
Packit Service 31306d
Packit Service 31306d
  if(ssh_connect(session)){
Packit Service 31306d
      fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
Packit Service 31306d
      return -1;
Packit Service 31306d
  }
Packit Service 31306d
  state=verify_knownhost(session);
Packit Service 31306d
  if (state != 0)
Packit Service 31306d
  	return -1;
Packit Service 31306d
  ssh_userauth_none(session, NULL);
Packit Service 31306d
  banner=ssh_get_issue_banner(session);
Packit Service 31306d
  if(banner){
Packit Service 31306d
      printf("%s\n",banner);
Packit Service 31306d
      free(banner);
Packit Service 31306d
  }
Packit Service 31306d
  auth=authenticate_console(session);
Packit Service 31306d
  if(auth != SSH_AUTH_SUCCESS){
Packit Service 31306d
  	return -1;
Packit Service 31306d
  }
Packit Service 31306d
 	forwarding(session);
Packit Service 31306d
  return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
#ifdef WITH_PCAP
Packit Service 31306d
ssh_pcap_file pcap;
Packit Service 31306d
void set_pcap(ssh_session session);
Packit Service 31306d
void set_pcap(ssh_session session){
Packit Service 31306d
	if(!pcap_file)
Packit Service 31306d
		return;
Packit Service 31306d
	pcap=ssh_pcap_file_new();
Packit Service 31306d
	if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
Packit Service 31306d
		printf("Error opening pcap file\n");
Packit Service 31306d
		ssh_pcap_file_free(pcap);
Packit Service 31306d
		pcap=NULL;
Packit Service 31306d
		return;
Packit Service 31306d
	}
Packit Service 31306d
	ssh_set_pcap_file(session,pcap);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
void cleanup_pcap(void);
Packit Service 31306d
void cleanup_pcap(){
Packit Service 31306d
	ssh_pcap_file_free(pcap);
Packit Service 31306d
	pcap=NULL;
Packit Service 31306d
}
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
int main(int argc, char **argv){
Packit Service 31306d
    ssh_session session;
Packit Service 31306d
Packit Service 31306d
    session = ssh_new();
Packit Service 31306d
Packit Service 31306d
    if(ssh_options_getopt(session, &argc, argv)) {
Packit Service 31306d
      fprintf(stderr, "error parsing command line :%s\n",
Packit Service 31306d
          ssh_get_error(session));
Packit Service 31306d
      usage();
Packit Service 31306d
    }
Packit Service 31306d
    opts(argc,argv);
Packit Service 31306d
#ifdef WITH_PCAP
Packit Service 31306d
    set_pcap(session);
Packit Service 31306d
#endif
Packit Service 31306d
    client(session);
Packit Service 31306d
Packit Service 31306d
    ssh_disconnect(session);
Packit Service 31306d
    ssh_free(session);
Packit Service 31306d
#ifdef WITH_PCAP
Packit Service 31306d
    cleanup_pcap();
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    ssh_finalize();
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}