5768791 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11]$ cat -n sample.c
  1 /* client.c */
  2 /*
  3 Copyright 2003 Aris Adamantiadis
  4 
  5 This file is part of the SSH Library
  6 
  7 You are free to copy this file, modify it in any way, consider it being public
  8 domain. This does not apply to the rest of the library though, but it is 
  9 allowed to cut-and-paste working code from this file to any license of
 10 program.
 11 The goal is to show the API in action. It's not a reference on how terminal
 12 clients must be made or how a client should react.
 13 */
 14 
 15 #include <stdio.h>
 16 #include <unistd.h>
 17 #include <stdlib.h>
 18 #include <string.h>
 19 #include <termios.h>
 20 
 21 #include <sys/select.h>
 22 #include <sys/time.h>
 23 #include <pty.h>
 24 #include <signal.h>
 25 #include <errno.h>
 26 #include <libssh/libssh.h>
 27 #include <libssh/sftp.h>
 28 
 29 #include <fcntl.h>
 30 
 31 #define MAXCMD 10
 32 char *host;
 33 char *user;
 34 int sftp;
 35 char *cmds[MAXCMD];
 36 struct termios terminal;
 37 void do_sftp(SSH_SESSION *session);
 38 
 39 void add_cmd(char *cmd){
 40     int n;
 41     for(n=0;cmds[n] && (n<MAXCMD);n++);
 42     if(n==MAXCMD)
 43         return;
 44     cmds[n]=strdup(cmd);
 45 }
 46 
 47 void usage(){
 48     fprintf(stderr,"Usage : ssh [options] [login@]hostname\n"
 49     "Options :\n"
 50     "  -l user : log in as user\n"
 51     "  -p port : connect to port\n"
 52     "  -d : use DSS to verify host public key\n"
 53     "  -r : use RSA to verify host public key\n");
 54     exit(0);
 55 }
 56 
 57 int opts(int argc, char **argv){
 58     int i;
 59     if(strstr(argv[0],"sftp"))
 60         sftp=1;
 61 //    for(i=0;i<argc;i++)
 62 //        printf("%d : %s\n",i,argv[i]);
 63     /* insert your own arguments here */
 64     while((i=getopt(argc,argv,""))!=-1){
 65         switch(i){
 66             default:
 67                 fprintf(stderr,"unknown option %c\n",optopt);
 68                 usage();
 69         }
 70     }
 71     if(optind < argc)
 72         host=argv[optind++];
 73     while(optind < argc)
 74         add_cmd(argv[optind++]);
 75     if(host==NULL)
 76         usage();
 77     return 0;
 78 }
 79 
 80 void do_cleanup(){
 81     tcsetattr(0,TCSANOW,&terminal);
 82 }
 83 void do_exit(){
 84     do_cleanup();
 85     exit(0);
 86 }
 87 CHANNEL *chan;
 88 int signal_delayed=0;
 89 void setsignal();
 90 void sigwindowchanged(){
 91     signal_delayed=1;
 92 }
 93 void sizechanged(){
 94     struct winsize win = { 0, 0, 0, 0 };
 95     ioctl(1, TIOCGWINSZ, &win);
 96     channel_change_pty_size(chan,win.ws_col, win.ws_row);
 97 //    printf("Changed pty size\n");
 98     setsignal();
 99 }
100 void setsignal(){
101     signal(SIGWINCH,sigwindowchanged);
102     signal_delayed=0;
103 }
104 
105 void select_loop(SSH_SESSION *session,CHANNEL *channel){
106     fd_set fds;
107     struct timeval timeout;
108     char buffer[10];
109     BUFFER *readbuf=buffer_new();
110     CHANNEL *channels[]={channel,NULL};
111     CHANNEL *outchannel[2];
112     int lus;
113     int eof=0;
114     int ret;
115     while(channel){
116        /* when a signal is caught, ssh_select will return
117          * with SSH_EINTR, which means it should be started 
118          * again. It lets you handle the signal the faster you
119          * can, like in this window changed example. Of course, if
120          * your signal handler doesn't call libssh at all, you're
121          * free to handle signals directly in sighandler.
122          */
123         do{
124             FD_ZERO(&fds);
125             if(!eof)
126                 FD_SET(0,&fds);
127             timeout.tv_sec=30;
128             timeout.tv_usec=0;
129             ret=ssh_select(channels,outchannel,0+1,&fds,&timeout);
130             if(signal_delayed)
131                 sizechanged();        
132         } while (ret==SSH_EINTR);
133         if(FD_ISSET(0,&fds)){
134             lus=read(0,buffer,10);
135             if(lus){
136                 channel_write(channel,buffer,lus);
137             }
138             else{
139                 eof=1;
140                 channel_send_eof(channel);
141             }
142         }
143         if(outchannel[0]){
144             while(channel_poll(outchannel[0],0)){
145                 lus=channel_read(outchannel[0],readbuf,0,0);
146                 if(lus==-1){
147                     ssh_say(0,"error reading channel : %s\n",ssh_get_error(session));
148                     return;
149                 }
150                 if(lus==0){
151                     ssh_say(1,"EOF received\n");
152                 } else
153                     write(1,buffer_get(readbuf),lus);
154             }
155             while(channel_poll(outchannel[0],1)){ /* stderr */
156                 lus=channel_read(outchannel[0],readbuf,0,1);
157                 if(lus==-1){
158                     ssh_say(0,"error reading channel : %s\n",ssh_get_error(session));
159                     return;
160                 }
161                 if(lus==0){
162                     ssh_say(1,"EOF received\n");
163                 } else
164                     write(2,buffer_get(readbuf),lus);
165             }
166         }
167         if(!channel_is_open(channel)){
168             channel_free(channel);
169             channel=NULL;
170         }
171     }
172     buffer_free(readbuf);
173 }
174 
175 void shell(SSH_SESSION *session){
176     CHANNEL *channel;
177     struct termios terminal_local;
178     int interactive=isatty(0);
179     if(interactive){
180         tcgetattr(0,&terminal_local);
181         memcpy(&terminal,&terminal_local,sizeof(struct termios));
182         cfmakeraw(&terminal_local);
183         tcsetattr(0,TCSANOW,&terminal_local);
184         setsignal();
185     }
186     signal(SIGTERM,do_cleanup);
187     channel = channel_open_session(session);
188     chan=channel;
189     if(interactive){
190         channel_request_pty(channel);
191         sizechanged();
192     }
193     channel_request_shell(channel);
194     select_loop(session,channel);
195 }
196 void batch_shell(SSH_SESSION *session){
197     CHANNEL *channel;
198     char buffer[1024];
199     int i,s=0;
200     for(i=0;i<MAXCMD && cmds[i];++i)
201         s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
202     channel=channel_open_session(session);
203     if(channel_request_exec(channel,buffer)){
204         printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
205         return;
206     }
207     select_loop(session,channel);
208 }
209         
210 /* it's just a proof of concept code for sftp, till i write a real documentation about it */
211 void do_sftp(SSH_SESSION *session){
212     SFTP_SESSION *sftp=sftp_new(session);
213     SFTP_DIR *dir;
214     SFTP_ATTRIBUTES *file;
215     SFTP_FILE *fichier;
216     SFTP_FILE *to;
217     int len=1;
218     int i;
219     char data[8000];
220     if(!sftp){
221         ssh_say(0,"sftp error initialising channel : %s\n",ssh_get_error(session));
222         return;
223     }
224     if(sftp_init(sftp)){
225         ssh_say(0,"error initialising sftp : %s\n",ssh_get_error(session));
226         return;
227     }
228     /* the connection is made */
229     /* opening a directory */
230     dir=sftp_opendir(sftp,"./");
231     if(!dir) {
232         ssh_say(0,"Directory not opened(%s)\n",ssh_get_error(session));
233         return ;
234     }
235     /* reading the whole directory, file by file */
236     while((file=sftp_readdir(sftp,dir))){
237         ssh_say(0,"%30s(%.8lo) : %.5d.%.5d : %.10lld
	bytes\n",file->name,file->permissions,file->uid,file->gid,file->size);
238         sftp_attributes_free(file);
239     }
240     /* when file=NULL, an error has occured OR the directory listing is end of file */
241     if(!sftp_dir_eof(dir)){
242         ssh_say(0,"error : %s\n",ssh_get_error(session));
243         return;
244     }
245     if(sftp_dir_close(dir)){
246         ssh_say(0,"Error : %s\n",ssh_get_error(session));
247         return;
248     }
249     /* this will open a file and copy it into your /home directory */
250     /* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without
	problem */
251 
252     fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY,NULL);
253     if(!fichier){
254         ssh_say(0,"Error opening /usr/bin/ssh : %s\n",ssh_get_error(session));
255         return;
256     }
257     /* open a file for writing... */
258     to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT,NULL);
259     if(!to){
260         ssh_say(0,"Error opening ssh-copy for writing : %s\n",ssh_get_error(session));
261         return;
262     }
263     while((len=sftp_read(fichier,data,4096)) > 0){
264         if(sftp_write(to,data,len)!=len){
265             ssh_say(0,"error writing %d bytes : %s\n",len,ssh_get_error(session));
266             return;
267         }
268     }
269     printf("finished\n");
270     if(len<0)
271         ssh_say(0,"Error reading file : %s\n",ssh_get_error(session));     
272     sftp_file_close(fichier);
273     sftp_file_close(to);
274     printf("fichiers fermés\n");
275     to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT,NULL);
276     for(i=0;i<1000;++i){
277         len=sftp_write(to,data,8000);
278         printf("wrote %d bytes\n",len);
279         if(len != 8000){
280             printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
281         }
282     }
283     sftp_file_close(to);
284     /* close the sftp session */
285     sftp_free(sftp);
286     printf("session sftp terminée\n");
287 }
288 int auth_kbdint(SSH_SESSION *session){
289     int err=ssh_userauth_kbdint(session,NULL,NULL);
290     char *name,*instruction,*prompt,*ptr;
291     char buffer[128];
292     int i,n;
293     char echo;
294     while (err==SSH_AUTH_INFO){
295         name=ssh_userauth_kbdint_getname(session);
296         instruction=ssh_userauth_kbdint_getinstruction(session);
297         n=ssh_userauth_kbdint_getnprompts(session);
298         if(strlen(name)>0)
299             printf("%s\n",name);
300         if(strlen(instruction)>0)
301             printf("%s\n",instruction);
302         for(i=0;i<n;++i){
303             prompt=ssh_userauth_kbdint_getprompt(session,i,&echo);
304             if(echo){
305                 printf("%s",prompt);
306                 fgets(buffer,sizeof(buffer),stdin);
307                 buffer[sizeof(buffer)-1]=0;
308                 if((ptr=strchr(buffer,'\n')))
309                     *ptr=0;
310                 ssh_userauth_kbdint_setanswer(session,i,buffer);
311                 memset(buffer,0,strlen(buffer));
312             } else {
313                 ptr=getpass(prompt);
314                 ssh_userauth_kbdint_setanswer(session,i,ptr);
315             }
316         }
317         err=ssh_userauth_kbdint(session,NULL,NULL);
318     }
319     return err;
320 }
321 
322 int main(int argc, char **argv){
323     SSH_SESSION *session;
324     SSH_OPTIONS *options;
325     int auth=0;
326     char *password;
327     char *banner;
328     int state;
329     char buf[10];
330     char hash[MD5_DIGEST_LEN];
331 
332     options=ssh_getopt(&argc, argv);
333     if(!options){
334         fprintf(stderr,"Error : %s\n",ssh_get_error(NULL));
335         usage();
336         return -1;
337     }    
338     opts(argc,argv);
339     signal(SIGTERM,do_exit);
340     if(user)
341         options_set_username(options,user);
342     options_set_host(options,host);
343     session=ssh_connect(options);
344     if(!session){
345         fprintf(stderr,"Connection failed : %s\n",ssh_get_error(NULL));
346         return -1;
347     }
348 
349     state=ssh_is_server_known(session);
350     switch(state){
351         case SSH_SERVER_KNOWN_OK:
352             break; /* ok */
353         case SSH_SERVER_KNOWN_CHANGED:
354             fprintf(stderr,"Host key for server changed : server's one is now :\n");
355             ssh_get_pubkey_hash(session,hash);
356             ssh_print_hexa("Public key hash",hash,MD5_DIGEST_LEN);
357             fprintf(stderr,"For security reason, connection will be stopped\n");
358             ssh_disconnect(session);
359             exit(-1);
360         case SSH_SERVER_FOUND_OTHER:
361             fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
362             fprintf(stderr,"An attacker might change the default server key to confuse your client"
363                 "into thinking the key does not exist\n"
364                 "We advise you to rerun the client with -d or -r for more safety.\n");
365                 ssh_disconnect(session);
366                 exit(-1);
367         case SSH_SERVER_NOT_KNOWN:
368             fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
369             ssh_get_pubkey_hash(session,hash);
370             ssh_print_hexa("Public key hash",hash,MD5_DIGEST_LEN);
371             fgets(buf,sizeof(buf),stdin);
372             if(strncasecmp(buf,"yes",3)!=0){
373                 ssh_disconnect(session);
374                 exit(-1);
375             }
376             fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
377             fgets(buf,sizeof(buf),stdin);
378             if(strncasecmp(buf,"yes",3)==0){
379                 if(ssh_write_knownhost(session))
380                     fprintf(stderr,"error %s\n",ssh_get_error(session));
381             }
382             
383             break;
384         case SSH_SERVER_ERROR:
385             fprintf(stderr,"%s",ssh_get_error(session));
386             ssh_disconnect(session);
387             exit(-1);
388     }
389 
390     /* no ? you should :) */
391     auth=ssh_userauth_autopubkey(session);
392     if(auth==SSH_AUTH_ERROR){
393         fprintf(stderr,"Authenticating with pubkey: %s\n",ssh_get_error(session));
394         return -1;
395     }
396     banner=ssh_get_issue_banner(session);
397     if(banner){
398         printf("%s\n",banner);
399         free(banner);
400     }
401     if(auth!=SSH_AUTH_SUCCESS){
402         auth=auth_kbdint(session);
403         if(auth==SSH_AUTH_ERROR){
404             fprintf(stderr,"authenticating with keyb-interactive: %s\n",
405                     ssh_get_error(session));
406             return -1;
407         }
408     }
409     if(auth!=SSH_AUTH_SUCCESS){
410         password=getpass("Password : ");
411         if(ssh_userauth_password(session,NULL,password) != SSH_AUTH_SUCCESS){
412             fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
413             ssh_disconnect(session);
414             return -1;
415         }
416         memset(password,0,strlen(password));
417     }
418     ssh_say(1,"Authentication success\n");
419     if(!sftp){
420         if(!cmds[0])
421             shell(session);
422         else
423             batch_shell(session);
424     }
425     else
426         do_sftp(session);    
427     if(!sftp && !cmds[0])
428         do_cleanup();
429     ssh_disconnect(session);
430     return 0;
431 }
5768792 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2005-03-04 19:54:59