sample.c | sample.c | |||
---|---|---|---|---|
/* client.c */ | /* client.c */ | |||
/* | /* | |||
Copyright 2003 Aris Adamantiadis | Copyright 2003-2009 Aris Adamantiadis | |||
This file is part of the SSH Library | This file is part of the SSH Library | |||
You are free to copy this file, modify it in any way, consider it being pub lic | You are free to copy this file, modify it in any way, consider it being pub lic | |||
domain. This does not apply to the rest of the library though, but it is | 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 | allowed to cut-and-paste working code from this file to any license of | |||
program. | program. | |||
The goal is to show the API in action. It's not a reference on how terminal | 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. | clients must be made or how a client should react. | |||
*/ | */ | |||
skipping to change at line 30 | skipping to change at line 30 | |||
#include <termios.h> | #include <termios.h> | |||
#include <sys/select.h> | #include <sys/select.h> | |||
#include <sys/time.h> | #include <sys/time.h> | |||
#ifdef HAVE_PTY_H | #ifdef HAVE_PTY_H | |||
#include <pty.h> | #include <pty.h> | |||
#endif | #endif | |||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | |||
#include <signal.h> | #include <signal.h> | |||
#include <errno.h> | #include <errno.h> | |||
#include <libssh/callbacks.h> | ||||
#include <libssh/libssh.h> | #include <libssh/libssh.h> | |||
#include <libssh/sftp.h> | #include <libssh/sftp.h> | |||
#include <fcntl.h> | #include <fcntl.h> | |||
#include "examples_common.h" | ||||
#define MAXCMD 10 | #define MAXCMD 10 | |||
char *host; | char *host; | |||
char *user; | char *user; | |||
int sftp; | ||||
char *cmds[MAXCMD]; | char *cmds[MAXCMD]; | |||
struct termios terminal; | struct termios terminal; | |||
void do_sftp(SSH_SESSION *session); | ||||
#ifdef WITH_PCAP | ||||
/* this header file won't be necessary in the future */ | ||||
#include <libssh/pcap.h> | ||||
char *pcap_file=NULL; | ||||
#endif | ||||
static int auth_callback(const char *prompt, char *buf, size_t len, | ||||
int echo, int verify, void *userdata) { | ||||
char *answer = NULL; | ||||
char *ptr; | ||||
(void) verify; | ||||
(void) userdata; | ||||
if (echo) { | ||||
while ((answer = fgets(buf, len, stdin)) == NULL); | ||||
if ((ptr = strchr(buf, '\n'))) { | ||||
ptr = '\0'; | ||||
} | ||||
} else { | ||||
answer = getpass(prompt); | ||||
} | ||||
if (answer == NULL) { | ||||
return -1; | ||||
} | ||||
strncpy(buf, answer, len); | ||||
return 0; | ||||
} | ||||
struct ssh_callbacks_struct cb = { | ||||
.auth_function=auth_callback, | ||||
.userdata=NULL | ||||
}; | ||||
static void add_cmd(char *cmd){ | static void add_cmd(char *cmd){ | |||
int n; | int n; | |||
for(n=0;cmds[n] && (n<MAXCMD);n++); | for(n=0;cmds[n] && (n<MAXCMD);n++); | |||
if(n==MAXCMD) | if(n==MAXCMD) | |||
return; | return; | |||
cmds[n]=strdup(cmd); | cmds[n]=strdup(cmd); | |||
} | } | |||
static void usage(){ | static void usage(){ | |||
fprintf(stderr,"Usage : ssh [options] [login@]hostname\n" | fprintf(stderr,"Usage : ssh [options] [login@]hostname\n" | |||
"sample client - libssh-%s\n" | "sample client - libssh-%s\n" | |||
"Options :\n" | "Options :\n" | |||
" -l user : log in as user\n" | " -l user : log in as user\n" | |||
" -p port : connect to port\n" | " -p port : connect to port\n" | |||
" -d : use DSS to verify host public key\n" | " -d : use DSS to verify host public key\n" | |||
" -r : use RSA to verify host public key\n", | " -r : use RSA to verify host public key\n" | |||
#ifdef WITH_PCAP | ||||
" -P file : create a pcap debugging file\n" | ||||
#endif | ||||
, | ||||
ssh_version(0)); | ssh_version(0)); | |||
exit(0); | exit(0); | |||
} | } | |||
static int opts(int argc, char **argv){ | static int opts(int argc, char **argv){ | |||
int i; | int i; | |||
if(strstr(argv[0],"sftp")) | ||||
sftp=1; | ||||
// for(i=0;i<argc;i++) | // for(i=0;i<argc;i++) | |||
// printf("%d : %s\n",i,argv[i]); | // printf("%d : %s\n",i,argv[i]); | |||
/* insert your own arguments here */ | /* insert your own arguments here */ | |||
while((i=getopt(argc,argv,""))!=-1){ | while((i=getopt(argc,argv,"P:"))!=-1){ | |||
switch(i){ | switch(i){ | |||
#ifdef WITH_PCAP | ||||
case 'P': | ||||
pcap_file=optarg; | ||||
break; | ||||
#endif | ||||
default: | default: | |||
fprintf(stderr,"unknown option %c\n",optopt); | fprintf(stderr,"unknown option %c\n",optopt); | |||
usage(); | usage(); | |||
} | } | |||
} | } | |||
if(optind < argc) | if(optind < argc) | |||
host=argv[optind++]; | host=argv[optind++]; | |||
while(optind < argc) | while(optind < argc) | |||
add_cmd(argv[optind++]); | add_cmd(argv[optind++]); | |||
if(host==NULL) | if(host==NULL) | |||
skipping to change at line 111 | skipping to change at line 155 | |||
} | } | |||
static void do_exit(int i) { | static void do_exit(int i) { | |||
/* unused variable */ | /* unused variable */ | |||
(void) i; | (void) i; | |||
do_cleanup(0); | do_cleanup(0); | |||
exit(0); | exit(0); | |||
} | } | |||
CHANNEL *chan; | ssh_channel chan; | |||
int signal_delayed=0; | int signal_delayed=0; | |||
static void sigwindowchanged(int i){ | static void sigwindowchanged(int i){ | |||
(void) i; | (void) i; | |||
signal_delayed=1; | signal_delayed=1; | |||
} | } | |||
static void setsignal(void){ | static void setsignal(void){ | |||
signal(SIGWINCH, sigwindowchanged); | signal(SIGWINCH, sigwindowchanged); | |||
signal_delayed=0; | signal_delayed=0; | |||
} | } | |||
static void sizechanged(void){ | static void sizechanged(void){ | |||
struct winsize win = { 0, 0, 0, 0 }; | struct winsize win = { 0, 0, 0, 0 }; | |||
ioctl(1, TIOCGWINSZ, &win); | ioctl(1, TIOCGWINSZ, &win); | |||
channel_change_pty_size(chan,win.ws_col, win.ws_row); | channel_change_pty_size(chan,win.ws_col, win.ws_row); | |||
// printf("Changed pty size\n"); | // printf("Changed pty size\n"); | |||
setsignal(); | setsignal(); | |||
} | } | |||
static void select_loop(SSH_SESSION *session,CHANNEL *channel){ | ||||
/* There are two flavors of select loop: the one based on | ||||
* ssh_select and the one based on channel_select. | ||||
* The ssh_select one permits you to give your own file descriptors to | ||||
* follow. It is thus a complete select loop. | ||||
* The second one only selects on channels. It is simplier to use | ||||
* but doesn't permit you to fill in your own file descriptor. It is | ||||
* more adapted if you can't use ssh_select as a main loop (because | ||||
* you already have another main loop system). | ||||
*/ | ||||
#ifdef USE_CHANNEL_SELECT | ||||
/* channel_select base main loop, with a standard select(2) | ||||
*/ | ||||
static void select_loop(ssh_session session,ssh_channel channel){ | ||||
fd_set fds; | fd_set fds; | |||
struct timeval timeout; | struct timeval timeout; | |||
char buffer[10]; | char buffer[4096]; | |||
BUFFER *readbuf=buffer_new(); | ssh_buffer readbuf=buffer_new(); | |||
CHANNEL *channels[2]; | ssh_channel channels[2]; | |||
int lus; | int lus; | |||
int eof=0; | int eof=0; | |||
int maxfd; | int maxfd; | |||
int ret; | int ret; | |||
while(channel){ | while(channel){ | |||
/* when a signal is caught, ssh_select will return | /* when a signal is caught, ssh_select will return | |||
* with SSH_EINTR, which means it should be started | * with SSH_EINTR, which means it should be started | |||
* again. It lets you handle the signal the faster you | * again. It lets you handle the signal the faster you | |||
* can, like in this window changed example. Of course, if | * can, like in this window changed example. Of course, if | |||
* your signal handler doesn't call libssh at all, you're | * your signal handler doesn't call libssh at all, you're | |||
skipping to change at line 161 | skipping to change at line 220 | |||
if(!eof) | if(!eof) | |||
FD_SET(0,&fds); | FD_SET(0,&fds); | |||
timeout.tv_sec=30; | timeout.tv_sec=30; | |||
timeout.tv_usec=0; | timeout.tv_usec=0; | |||
FD_SET(ssh_get_fd(session),&fds); | FD_SET(ssh_get_fd(session),&fds); | |||
maxfd=ssh_get_fd(session)+1; | maxfd=ssh_get_fd(session)+1; | |||
ret=select(maxfd,&fds,NULL,NULL,&timeout); | ret=select(maxfd,&fds,NULL,NULL,&timeout); | |||
if(ret==EINTR) | if(ret==EINTR) | |||
continue; | continue; | |||
if(FD_ISSET(0,&fds)){ | if(FD_ISSET(0,&fds)){ | |||
lus=read(0,buffer,10); | lus=read(0,buffer,sizeof(buffer)); | |||
if(lus) | if(lus) | |||
channel_write(channel,buffer,lus); | channel_write(channel,buffer,lus); | |||
else { | else { | |||
eof=1; | eof=1; | |||
channel_send_eof(channel); | channel_send_eof(channel); | |||
} | } | |||
} | } | |||
if(FD_ISSET(ssh_get_fd(session),&fds)){ | if(FD_ISSET(ssh_get_fd(session),&fds)){ | |||
ssh_set_fd_toread(session); | ssh_set_fd_toread(session); | |||
} | } | |||
skipping to change at line 228 | skipping to change at line 287 | |||
write(2,buffer_get(readbuf),lus); | write(2,buffer_get(readbuf),lus); | |||
} | } | |||
} | } | |||
if(channel && channel_is_closed(channel)){ | if(channel && channel_is_closed(channel)){ | |||
channel_free(channel); | channel_free(channel); | |||
channel=NULL; | channel=NULL; | |||
} | } | |||
} | } | |||
buffer_free(readbuf); | buffer_free(readbuf); | |||
} | } | |||
#else /* CHANNEL_SELECT */ | ||||
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 wan | ||||
t to read from | ||||
channels[1]=NULL; | ||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&time | ||||
out); | ||||
if(signal_delayed) | ||||
sizechanged(); | ||||
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,size | ||||
of(buffer),0); | ||||
if(lus==-1){ | ||||
fprintf(stderr, "Error readi | ||||
ng channel: %s\n", | ||||
ssh_get_erro | ||||
r(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,size | ||||
of(buffer),1); | ||||
if(lus==-1){ | ||||
fprintf(stderr, "Error readi | ||||
ng channel: %s\n", | ||||
ssh_get_erro | ||||
r(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); | ||||
} | ||||
} | ||||
#endif | ||||
static void shell(SSH_SESSION *session){ | static void shell(ssh_session session){ | |||
CHANNEL *channel; | ssh_channel channel; | |||
struct termios terminal_local; | struct termios terminal_local; | |||
int interactive=isatty(0); | int interactive=isatty(0); | |||
channel = channel_new(session); | channel = channel_new(session); | |||
if(interactive){ | if(interactive){ | |||
tcgetattr(0,&terminal_local); | tcgetattr(0,&terminal_local); | |||
memcpy(&terminal,&terminal_local,sizeof(struct termios)); | memcpy(&terminal,&terminal_local,sizeof(struct termios)); | |||
} | } | |||
if(channel_open_session(channel)){ | if(channel_open_session(channel)){ | |||
printf("error opening channel : %s\n",ssh_get_error(session)); | printf("error opening channel : %s\n",ssh_get_error(session)); | |||
return; | return; | |||
skipping to change at line 258 | skipping to change at line 406 | |||
printf("Requesting shell : %s\n",ssh_get_error(session)); | printf("Requesting shell : %s\n",ssh_get_error(session)); | |||
return; | return; | |||
} | } | |||
if(interactive){ | if(interactive){ | |||
cfmakeraw(&terminal_local); | cfmakeraw(&terminal_local); | |||
tcsetattr(0,TCSANOW,&terminal_local); | tcsetattr(0,TCSANOW,&terminal_local); | |||
setsignal(); | setsignal(); | |||
} | } | |||
signal(SIGTERM,do_cleanup); | signal(SIGTERM,do_cleanup); | |||
select_loop(session,channel); | select_loop(session,channel); | |||
if(interactive) | ||||
do_cleanup(0); | ||||
} | } | |||
static void batch_shell(SSH_SESSION *session){ | static void batch_shell(ssh_session session){ | |||
CHANNEL *channel; | ssh_channel channel; | |||
char buffer[1024]; | char buffer[1024]; | |||
int i,s=0; | int i,s=0; | |||
for(i=0;i<MAXCMD && cmds[i];++i) | for(i=0;i<MAXCMD && cmds[i];++i) | |||
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]); | s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]); | |||
channel=channel_new(session); | channel=channel_new(session); | |||
channel_open_session(channel); | channel_open_session(channel); | |||
if(channel_request_exec(channel,buffer)){ | if(channel_request_exec(channel,buffer)){ | |||
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session )); | printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session )); | |||
return; | return; | |||
} | } | |||
select_loop(session,channel); | select_loop(session,channel); | |||
} | } | |||
#ifdef WITH_SFTP | static int client(ssh_session session){ | |||
/* it's just a proof of concept code for sftp, till i write a real document | int auth=0; | |||
ation about it */ | char *banner; | |||
void do_sftp(SSH_SESSION *session){ | int state; | |||
SFTP_SESSION *sftp_session=sftp_new(session); | if (user) | |||
SFTP_DIR *dir; | if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) | |||
SFTP_ATTRIBUTES *file; | return -1; | |||
SFTP_FILE *fichier; | if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) | |||
SFTP_FILE *to; | return -1; | |||
int len=1; | ||||
int i; | ssh_options_parse_config(session, NULL); | |||
char data[8000]; | ||||
if(!sftp_session){ | if(ssh_connect(session)){ | |||
fprintf(stderr, "sftp error initialising channel: %s\n", | fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session)); | |||
ssh_get_error(session)); | return -1; | |||
return; | } | |||
} | state=verify_knownhost(session); | |||
if(sftp_init(sftp_session)){ | if (state != 0) | |||
fprintf(stderr, "error initialising sftp: %s\n", | return -1; | |||
ssh_get_error(session)); | ssh_userauth_none(session, NULL); | |||
return; | banner=ssh_get_issue_banner(session); | |||
} | if(banner){ | |||
/* the connection is made */ | printf("%s\n",banner); | |||
/* opening a directory */ | free(banner); | |||
dir=sftp_opendir(sftp_session,"./"); | } | |||
if(!dir) { | auth=authenticate_console(session); | |||
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session | if(auth != SSH_AUTH_SUCCESS){ | |||
)); | return -1; | |||
return ; | } | |||
} | ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success"); | |||
/* reading the whole directory, file by file */ | if(!cmds[0]) | |||
while((file=sftp_readdir(sftp_session,dir))){ | shell(session); | |||
fprintf(stderr, "%30s(%.8o) : %.5d.%.5d : %.10llu bytes\n", | else | |||
file->name, | batch_shell(session); | |||
file->permissions, | return 0; | |||
file->uid, | } | |||
file->gid, | ||||
(long long unsigned int) file->size); | #ifdef WITH_PCAP | |||
sftp_attributes_free(file); | ssh_pcap_file pcap; | |||
} | void set_pcap(ssh_session session); | |||
/* when file=NULL, an error has occured OR the directory listing is end | void set_pcap(ssh_session session){ | |||
of file */ | if(!pcap_file) | |||
if(!sftp_dir_eof(dir)){ | return; | |||
fprintf(stderr, "Error: %s\n", ssh_get_error(session)); | pcap=ssh_pcap_file_new(); | |||
return; | if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){ | |||
} | printf("Error opening pcap file\n"); | |||
if(sftp_closedir(dir)){ | ssh_pcap_file_free(pcap); | |||
fprintf(stderr, "Error: %s\n", ssh_get_error(session)); | pcap=NULL; | |||
return; | return; | |||
} | } | |||
/* this will open a file and copy it into your /home directory */ | ssh_set_pcap_file(session,pcap); | |||
/* the small buffer size was intended to stress the library. of course, | } | |||
you can use a buffer till 20kbytes without problem */ | ||||
void cleanup_pcap(void); | ||||
fichier=sftp_open(sftp_session,"/usr/bin/ssh",O_RDONLY, 0); | void cleanup_pcap(){ | |||
if(!fichier){ | ssh_pcap_file_free(pcap); | |||
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n", | pcap=NULL; | |||
ssh_get_error(session)); | ||||
return; | ||||
} | ||||
/* open a file for writing... */ | ||||
to=sftp_open(sftp_session,"ssh-copy",O_WRONLY | O_CREAT, 0); | ||||
if(!to){ | ||||
fprintf(stderr, "Error opening ssh-copy for writing: %s\n", | ||||
ssh_get_error(session)); | ||||
return; | ||||
} | ||||
while((len=sftp_read(fichier,data,4096)) > 0){ | ||||
if(sftp_write(to,data,len)!=len){ | ||||
fprintf(stderr, "Error writing %d bytes: %s\n", | ||||
len, ssh_get_error(session)); | ||||
return; | ||||
} | ||||
} | ||||
printf("finished\n"); | ||||
if(len<0) | ||||
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session)) | ||||
; | ||||
sftp_close(fichier); | ||||
sftp_close(to); | ||||
printf("fichiers ferm\n"); | ||||
to=sftp_open(sftp_session,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644); | ||||
for(i=0;i<1000;++i){ | ||||
len=sftp_write(to,data,8000); | ||||
printf("wrote %d bytes\n",len); | ||||
if(len != 8000){ | ||||
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session)); | ||||
} | ||||
} | ||||
sftp_close(to); | ||||
/* close the sftp session */ | ||||
sftp_free(sftp_session); | ||||
printf("session sftp termin�\n"); | ||||
} | } | |||
#endif | #endif | |||
static int auth_kbdint(SSH_SESSION *session){ | ||||
int err=ssh_userauth_kbdint(session,NULL,NULL); | ||||
const char *name, *instruction, *prompt; | ||||
char *ptr; | ||||
char buffer[128]; | ||||
int i,n; | ||||
char echo; | ||||
while (err==SSH_AUTH_INFO){ | ||||
name=ssh_userauth_kbdint_getname(session); | ||||
instruction=ssh_userauth_kbdint_getinstruction(session); | ||||
n=ssh_userauth_kbdint_getnprompts(session); | ||||
if(strlen(name)>0) | ||||
printf("%s\n",name); | ||||
if(strlen(instruction)>0) | ||||
printf("%s\n",instruction); | ||||
for(i=0;i<n;++i){ | ||||
prompt=ssh_userauth_kbdint_getprompt(session,i,&echo); | ||||
if(echo){ | ||||
printf("%s",prompt); | ||||
fgets(buffer,sizeof(buffer),stdin); | ||||
buffer[sizeof(buffer)-1]=0; | ||||
if((ptr=strchr(buffer,'\n'))) | ||||
*ptr=0; | ||||
if (ssh_userauth_kbdint_setanswer(session,i,buffer) < 0) { | ||||
return SSH_AUTH_ERROR; | ||||
} | ||||
memset(buffer,0,strlen(buffer)); | ||||
} else { | ||||
ptr=getpass(prompt); | ||||
if (ssh_userauth_kbdint_setanswer(session,i,ptr) < 0) { | ||||
return SSH_AUTH_ERROR; | ||||
} | ||||
} | ||||
} | ||||
err=ssh_userauth_kbdint(session,NULL,NULL); | ||||
} | ||||
return err; | ||||
} | ||||
int main(int argc, char **argv){ | int main(int argc, char **argv){ | |||
SSH_SESSION *session; | ssh_session session; | |||
SSH_OPTIONS *options; | ||||
int auth=0; | ||||
char *password; | ||||
char *banner; | ||||
char *hexa; | ||||
int state; | ||||
char buf[10]; | ||||
unsigned char *hash = NULL; | ||||
int hlen; | ||||
options=ssh_options_new(); | ||||
if(ssh_options_getopt(options,&argc, argv)){ | ||||
fprintf(stderr,"error parsing command line :%s\n",ssh_get_error(opti | ||||
ons)); | ||||
usage(); | ||||
} | ||||
opts(argc,argv); | ||||
signal(SIGTERM, do_exit); | ||||
if (user) { | ||||
if (ssh_options_set_username(options,user) < 0) { | ||||
ssh_options_free(options); | ||||
return 1; | ||||
} | ||||
} | ||||
if (ssh_options_set_host(options,host) < 0) { | session = ssh_new(); | |||
ssh_options_free(options); | ||||
return 1; | ||||
} | ||||
session=ssh_new(); | ||||
ssh_set_options(session,options); | ||||
if(ssh_connect(session)){ | ||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session)); | ||||
ssh_disconnect(session); | ||||
ssh_finalize(); | ||||
return 1; | ||||
} | ||||
state=ssh_is_server_known(session); | ||||
hlen = ssh_get_pubkey_hash(session, &hash); | ssh_callbacks_init(&cb); | |||
if (hlen < 0) { | ssh_set_callbacks(session,&cb); | |||
ssh_disconnect(session); | ||||
ssh_finalize(); | ||||
return 1; | ||||
} | ||||
switch(state){ | ||||
case SSH_SERVER_KNOWN_OK: | ||||
break; /* ok */ | ||||
case SSH_SERVER_KNOWN_CHANGED: | ||||
fprintf(stderr,"Host key for server changed : server's one is n | ||||
ow :\n"); | ||||
ssh_print_hexa("Public key hash",hash, hlen); | ||||
free(hash); | ||||
fprintf(stderr,"For security reason, connection will be stopped | ||||
\n"); | ||||
ssh_disconnect(session); | ||||
ssh_finalize(); | ||||
exit(-1); | ||||
case SSH_SERVER_FOUND_OTHER: | ||||
fprintf(stderr,"The host key for this server was not found but | ||||
an other type of key exists.\n"); | ||||
fprintf(stderr,"An attacker might change the default server key | ||||
to confuse your client" | ||||
"into thinking the key does not exist\n" | ||||
"We advise you to rerun the client with -d or -r for more s | ||||
afety.\n"); | ||||
ssh_disconnect(session); | ||||
ssh_finalize(); | ||||
exit(-1); | ||||
case SSH_SERVER_FILE_NOT_FOUND: | ||||
fprintf(stderr,"Could not find known host file. If you accept t | ||||
he host key here,\n"); | ||||
fprintf(stderr,"the file will be automatically created.\n"); | ||||
/* fallback to SSH_SERVER_NOT_KNOWN behaviour */ | ||||
case SSH_SERVER_NOT_KNOWN: | ||||
hexa = ssh_get_hexa(hash, hlen); | ||||
fprintf(stderr,"The server is unknown. Do you trust the host ke | ||||
y ?\n"); | ||||
fprintf(stderr, "Public key hash: %s\n", hexa); | ||||
free(hexa); | ||||
fgets(buf,sizeof(buf),stdin); | ||||
if(strncasecmp(buf,"yes",3)!=0){ | ||||
ssh_disconnect(session); | ||||
exit(-1); | ||||
} | ||||
fprintf(stderr,"This new key will be written on disk for furthe | ||||
r usage. do you agree ?\n"); | ||||
fgets(buf,sizeof(buf),stdin); | ||||
if(strncasecmp(buf,"yes",3)==0){ | ||||
if (ssh_write_knownhost(session) < 0) { | ||||
free(hash); | ||||
fprintf(stderr, "error %s\n", strerror(errno)); | ||||
exit(-1); | ||||
} | ||||
} | ||||
break; | if(ssh_options_getopt(session, &argc, argv)) { | |||
case SSH_SERVER_ERROR: | fprintf(stderr, "error parsing command line :%s\n", | |||
free(hash); | ssh_get_error(session)); | |||
fprintf(stderr,"%s",ssh_get_error(session)); | usage(); | |||
ssh_disconnect(session); | ||||
ssh_finalize(); | ||||
exit(-1); | ||||
} | } | |||
free(hash); | opts(argc,argv); | |||
signal(SIGTERM, do_exit); | ||||
ssh_userauth_none(session, NULL); | #ifdef WITH_PCAP | |||
set_pcap(session); | ||||
auth = ssh_auth_list(session); | ||||
printf("auth: 0x%04x\n", auth); | ||||
printf("supported auth methods: "); | ||||
if (auth & SSH_AUTH_METHOD_PUBLICKEY) { | ||||
printf("publickey"); | ||||
} | ||||
if (auth & SSH_AUTH_METHOD_INTERACTIVE) { | ||||
printf(", keyboard-interactive"); | ||||
} | ||||
printf("\n"); | ||||
/* no ? you should :) */ | ||||
auth=ssh_userauth_autopubkey(session, NULL); | ||||
if(auth==SSH_AUTH_ERROR){ | ||||
fprintf(stderr,"Authenticating with pubkey: %s\n",ssh_get_error(ses | ||||
sion)); | ||||
ssh_finalize(); | ||||
return -1; | ||||
} | ||||
banner=ssh_get_issue_banner(session); | ||||
if(banner){ | ||||
printf("%s\n",banner); | ||||
free(banner); | ||||
} | ||||
if(auth!=SSH_AUTH_SUCCESS){ | ||||
auth=auth_kbdint(session); | ||||
if(auth==SSH_AUTH_ERROR){ | ||||
fprintf(stderr,"authenticating with keyb-interactive: %s\n", | ||||
ssh_get_error(session)); | ||||
ssh_finalize(); | ||||
return -1; | ||||
} | ||||
} | ||||
if(auth!=SSH_AUTH_SUCCESS){ | ||||
password=getpass("Password: "); | ||||
if(ssh_userauth_password(session,NULL,password) != SSH_AUTH_SUCCESS | ||||
){ | ||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(sess | ||||
ion)); | ||||
ssh_disconnect(session); | ||||
ssh_finalize(); | ||||
return -1; | ||||
} | ||||
memset(password,0,strlen(password)); | ||||
} | ||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success"); | ||||
if(strstr(argv[0],"sftp")){ | ||||
sftp=1; | ||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Doing sftp instead"); | ||||
} | ||||
if(!sftp){ | ||||
if(!cmds[0]) | ||||
shell(session); | ||||
else | ||||
batch_shell(session); | ||||
} | ||||
#ifdef WITH_SFTP | ||||
else | ||||
do_sftp(session); | ||||
#endif | #endif | |||
if(!sftp && !cmds[0]) | client(session); | |||
do_cleanup(0); | ||||
ssh_disconnect(session); | ssh_disconnect(session); | |||
ssh_free(session); | ||||
#ifdef WITH_PCAP | ||||
cleanup_pcap(); | ||||
#endif | ||||
ssh_finalize(); | ssh_finalize(); | |||
return 0; | return 0; | |||
} | } | |||
End of changes. 26 change blocks. | ||||
316 lines changed or deleted | 258 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |