From 58294442d3589f464571ff86071a260e0f548d26 Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Fri, 9 Oct 2009 21:44:05 +0200 Subject: Moved samples into examples directory --- examples/CMakeLists.txt | 16 ++ examples/sample.c | 669 ++++++++++++++++++++++++++++++++++++++++++++++++ examples/samplesshd.c | 152 +++++++++++ 3 files changed, 837 insertions(+) create mode 100644 examples/sample.c create mode 100644 examples/samplesshd.c (limited to 'examples') diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3dbf615..ddc95a7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,6 +8,7 @@ set(examples_SRCS include_directories( ${LIBSSH_PUBLIC_INCLUDE_DIRS} + ${LIBSSH_PRIVATE_INCLUDE_DIRS} ) add_executable(libssh_scp libssh_scp.c ${examples_SRCS}) @@ -16,3 +17,18 @@ add_executable(scp_download scp_download.c ${examples_SRCS}) target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY}) target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY}) +include_directories( + ${LIBSSH_PUBLIC_INCLUDE_DIRS} + ${LIBSSH_PRIVATE_INCLUDE_DIRS} +) + +if (WITH_SFTP) + add_executable(samplessh sample.c) + target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY}) +endif (WITH_SFTP) + +if (WITH_SERVER) + add_executable(samplesshd samplesshd.c) + target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY}) +endif (WITH_SERVER) + diff --git a/examples/sample.c b/examples/sample.c new file mode 100644 index 0000000..c2aaa66 --- /dev/null +++ b/examples/sample.c @@ -0,0 +1,669 @@ +/* client.c */ +/* +Copyright 2003-2009 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 +#ifdef HAVE_PTY_H +#include +#endif +#include +#include +#include +#include +#include + +#include + +#define MAXCMD 10 +char *host; +char *user; +int sftp; +char *cmds[MAXCMD]; +struct termios terminal; +void do_sftp(ssh_session session); + +static void add_cmd(char *cmd){ + int n; + for(n=0;cmds[n] && (nc_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + termios_p->c_oflag &= ~OPOST; + termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + termios_p->c_cflag &= ~(CSIZE|PARENB); + termios_p->c_cflag |= CS8; +} +#endif + + +static void do_cleanup(int i) { + /* unused variable */ + (void) i; + + tcsetattr(0,TCSANOW,&terminal); +} + +static void do_exit(int i) { + /* unused variable */ + (void) i; + + do_cleanup(0); + exit(0); +} + +ssh_channel chan; +int signal_delayed=0; + +static void sigwindowchanged(int i){ + (void) i; + signal_delayed=1; +} + +static void setsignal(void){ + signal(SIGWINCH, sigwindowchanged); + signal_delayed=0; +} + +static void sizechanged(void){ + struct winsize win = { 0, 0, 0, 0 }; + ioctl(1, TIOCGWINSZ, &win); + channel_change_pty_size(chan,win.ws_col, win.ws_row); +// printf("Changed pty size\n"); + setsignal(); +} +static void select_loop(ssh_session session,ssh_channel channel){ + fd_set fds; + struct timeval timeout; + char buffer[10]; + ssh_buffer readbuf=buffer_new(); + ssh_channel channels[2]; + int lus; + int eof=0; + int maxfd; + int ret; + while(channel){ + /* when a signal is caught, ssh_select will return + * with SSH_EINTR, which means it should be started + * again. It lets you handle the signal the faster you + * can, like in this window changed example. Of course, if + * your signal handler doesn't call libssh at all, you're + * free to handle signals directly in sighandler. + */ + 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; + ret=select(maxfd,&fds,NULL,NULL,&timeout); + if(ret==EINTR) + continue; + if(FD_ISSET(0,&fds)){ + lus=read(0,buffer,10); + if(lus) + channel_write(channel,buffer,lus); + else { + eof=1; + channel_send_eof(channel); + } + } + if(FD_ISSET(ssh_get_fd(session),&fds)){ + ssh_set_fd_toread(session); + } + channels[0]=channel; // set the first channel we want to read from + channels[1]=NULL; + ret=channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll + if(signal_delayed) + sizechanged(); + } while (ret==EINTR || ret==SSH_EINTR); + + // we already looked for input from stdin. Now, we are looking for input from the 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(channels[0]){ + while(channel && channel_is_open(channel) && channel_poll(channel,0)){ + lus=channel_read_buffer(channel,readbuf,0,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_get(readbuf),lus); + } + while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */ + lus=channel_read_buffer(channel,readbuf,0,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_get(readbuf),lus); + } + } + if(channel && channel_is_closed(channel)){ + channel_free(channel); + channel=NULL; + } + } + buffer_free(readbuf); +} + + +static void shell(ssh_session session){ + ssh_channel channel; + struct termios terminal_local; + int interactive=isatty(0); + channel = channel_new(session); + if(interactive){ + tcgetattr(0,&terminal_local); + memcpy(&terminal,&terminal_local,sizeof(struct termios)); + } + if(channel_open_session(channel)){ + printf("error opening channel : %s\n",ssh_get_error(session)); + return; + } + chan=channel; + if(interactive){ + channel_request_pty(channel); + sizechanged(); + } + if(channel_request_shell(channel)){ + printf("Requesting shell : %s\n",ssh_get_error(session)); + return; + } + if(interactive){ + cfmakeraw(&terminal_local); + tcsetattr(0,TCSANOW,&terminal_local); + setsignal(); + } + signal(SIGTERM,do_cleanup); + select_loop(session,channel); +} + +static void batch_shell(ssh_session session){ + ssh_channel channel; + char buffer[1024]; + int i,s=0; + for(i=0;if_bsize, + (unsigned long long) sftpstatvfs->f_frsize, + (unsigned long long) sftpstatvfs->f_blocks, + (unsigned long long) sftpstatvfs->f_bfree, + (unsigned long long) sftpstatvfs->f_bavail, + (unsigned long long) sftpstatvfs->f_files, + (unsigned long long) sftpstatvfs->f_ffree, + (unsigned long long) sftpstatvfs->f_favail, + (unsigned long long) sftpstatvfs->f_fsid, + (unsigned long long) sftpstatvfs->f_flag, + (unsigned long long) sftpstatvfs->f_namemax); + + sftp_statvfs_free(sftpstatvfs); + + if (statvfs("/tmp", &sysstatvfs) < 0) { + fprintf(stderr, "statvfs failed (%s)\n", strerror(errno)); + return; + } + + printf("sys statvfs:\n" + "\tfile system block size: %llu\n" + "\tfundamental fs block size: %llu\n" + "\tnumber of blocks (unit f_frsize): %llu\n" + "\tfree blocks in file system: %llu\n" + "\tfree blocks for non-root: %llu\n" + "\ttotal file inodes: %llu\n" + "\tfree file inodes: %llu\n" + "\tfree file inodes for to non-root: %llu\n" + "\tfile system id: %llu\n" + "\tbit mask of f_flag values: %llu\n" + "\tmaximum filename length: %llu\n", + (unsigned long long) sysstatvfs.f_bsize, + (unsigned long long) sysstatvfs.f_frsize, + (unsigned long long) sysstatvfs.f_blocks, + (unsigned long long) sysstatvfs.f_bfree, + (unsigned long long) sysstatvfs.f_bavail, + (unsigned long long) sysstatvfs.f_files, + (unsigned long long) sysstatvfs.f_ffree, + (unsigned long long) sysstatvfs.f_favail, + (unsigned long long) sysstatvfs.f_fsid, + (unsigned long long) sysstatvfs.f_flag, + (unsigned long long) sysstatvfs.f_namemax); + } + + /* the connection is made */ + /* opening a directory */ + dir=sftp_opendir(sftp_session,"./"); + if(!dir) { + fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session)); + return ; + } + /* reading the whole directory, file by file */ + while((file=sftp_readdir(sftp_session,dir))){ + fprintf(stderr, "%30s(%.8o) : %.5d.%.5d : %.10llu bytes\n", + file->name, + file->permissions, + file->uid, + file->gid, + (long long unsigned int) file->size); + sftp_attributes_free(file); + } + /* when file=NULL, an error has occured OR the directory listing is end of file */ + if(!sftp_dir_eof(dir)){ + fprintf(stderr, "Error: %s\n", ssh_get_error(session)); + return; + } + if(sftp_closedir(dir)){ + fprintf(stderr, "Error: %s\n", ssh_get_error(session)); + return; + } + /* this will open a file and copy it into your /home directory */ + /* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */ + + fichier=sftp_open(sftp_session,"/usr/bin/ssh",O_RDONLY, 0); + if(!fichier){ + fprintf(stderr, "Error opening /usr/bin/ssh: %s\n", + ssh_get_error(session)); + return; + } + /* open a file for writing... */ + to=sftp_open(sftp_session,"ssh-copy",O_WRONLY | O_CREAT, 0700); + 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("sftp session terminated\n"); +} +#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 +#include +#include +#include +#include +#ifndef KEYS_FOLDER +#ifdef _WIN32 +#define KEYS_FOLDER +#else +#define KEYS_FOLDER "/etc/ssh/" +#endif +#endif + +static int auth_password(char *user, char *password){ + if(strcmp(user,"aris")) + return 0; + if(strcmp(password,"lala")) + return 0; + return 1; // authenticated +} + +int main(int argc, char **argv){ + ssh_session session; + ssh_bind sshbind; + ssh_message message; + ssh_channel chan=0; + ssh_buffer buf; + int auth=0; + int sftp=0; + int i; + int r; + + sshbind=ssh_bind_new(); + session=ssh_new(); + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key"); + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key"); + + if(ssh_bind_listen(sshbind)<0){ + printf("Error listening to socket: %s\n",ssh_get_error(sshbind)); + return 1; + } + r=ssh_bind_accept(sshbind,session); + if(r==SSH_ERROR){ + printf("error accepting a connection : %s\n",ssh_get_error(sshbind)); + return 1; + } + if(ssh_accept(session)){ + printf("ssh_accept: %s\n",ssh_get_error(session)); + return 1; + } + do { + message=ssh_message_get(session); + if(!message) + break; + switch(ssh_message_type(message)){ + case SSH_REQUEST_AUTH: + switch(ssh_message_subtype(message)){ + case SSH_AUTH_METHOD_PASSWORD: + printf("User %s wants to auth with pass %s\n", + ssh_message_auth_user(message), + ssh_message_auth_password(message)); + if(auth_password(ssh_message_auth_user(message), + ssh_message_auth_password(message))){ + auth=1; + ssh_message_auth_reply_success(message,0); + break; + } + // not authenticated, send default message + case SSH_AUTH_METHOD_NONE: + default: + ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD); + ssh_message_reply_default(message); + break; + } + break; + default: + ssh_message_reply_default(message); + } + ssh_message_free(message); + } while (!auth); + if(!auth){ + printf("auth error: %s\n",ssh_get_error(session)); + ssh_disconnect(session); + return 1; + } + do { + message=ssh_message_get(session); + if(message){ + switch(ssh_message_type(message)){ + case SSH_REQUEST_CHANNEL_OPEN: + if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){ + chan=ssh_message_channel_request_open_reply_accept(message); + break; + } + default: + ssh_message_reply_default(message); + } + ssh_message_free(message); + } + } while(message && !chan); + if(!chan){ + printf("error : %s\n",ssh_get_error(session)); + ssh_finalize(); + return 1; + } + do { + message=ssh_message_get(session); + if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL && + ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){ +// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){ + sftp=1; + ssh_message_channel_request_reply_success(message); + break; + // } + } + if(!sftp){ + ssh_message_reply_default(message); + } + ssh_message_free(message); + } while (message && !sftp); + if(!sftp){ + printf("error : %s\n",ssh_get_error(session)); + return 1; + } + printf("it works !\n"); + buf=buffer_new(); + do{ + i=channel_read_buffer(chan,buf,0,0); + if(i>0) + write(1,buffer_get(buf),buffer_get_len(buf)); + } while (i>0); + buffer_free(buf); + ssh_disconnect(session); + ssh_bind_free(sshbind); + ssh_finalize(); + return 0; +} + -- cgit v1.2.3