[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: for help
[Thread Prev] | [Thread Next]
- Subject: Re: for help
- From: fan zhang <zf446886@xxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Tue, 4 Mar 2014 19:53:12 +0800
- To: libssh@xxxxxxxxxx
I use the function ssh_channel_pty_window_change_callback().but when I change window size ,it does not work.My test code is below: #include "config.h" #include <libssh/libssh.h> #include <libssh/server.h> #include <libssh/callbacks.h> #ifdef HAVE_ARGP_H #include <argp.h> #endif #include <stdlib.h> #include <string.h> #include <stdio.h> #include <poll.h> #ifdef HAVE_PTY_H #include <pty.h> #endif #ifdef HAVE_UTIL_H #include <util.h> #endif #ifdef HAVE_TERMIOS_H #include <termios.h> #endif #define SSHD_USER "libssh" #define SSHD_PASSWORD "libssh" #ifndef KEYS_FOLDER #ifdef _WIN32 #define KEYS_FOLDER #else #define KEYS_FOLDER "/etc/ssh/" #endif #endif static int port = 2222; #ifdef WITH_PCAP const char *pcap_file="debug.server.pcap"; ssh_pcap_file pcap; static 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); } static void cleanup_pcap(){ ssh_pcap_file_free(pcap); pcap=NULL; } #endif static int auth_password(const char *user, const char *password){ if(strcmp(user, SSHD_USER)) return 0; if(strcmp(password, SSHD_PASSWORD)) return 0; return 1; // authenticated } #ifdef HAVE_ARGP_H const char *argp_program_version = "libssh server example " SSH_STRINGIFY(LIBSSH_VERSION); const char *argp_program_bug_address = "<libssh@xxxxxxxxxx>"; /* Program documentation. */ static char doc[] = "libssh -- a Secure Shell protocol implementation"; /* A description of the arguments we accept. */ static char args_doc[] = "BINDADDR"; /* The options we understand. */ static struct argp_option options[] = { { .name = "port", .key = 'p', .arg = "PORT", .flags = 0, .doc = "Set the port to bind.", .group = 0 }, { .name = "hostkey", .key = 'k', .arg = "FILE", .flags = 0, .doc = "Set the host key.", .group = 0 }, { .name = "dsakey", .key = 'd', .arg = "FILE", .flags = 0, .doc = "Set the dsa key.", .group = 0 }, { .name = "rsakey", .key = 'r', .arg = "FILE", .flags = 0, .doc = "Set the rsa key.", .group = 0 }, { .name = "verbose", .key = 'v', .arg = NULL, .flags = 0, .doc = "Get verbose output.", .group = 0 }, {NULL, 0, 0, 0, NULL, 0} }; /* Parse a single option. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { /* Get the input argument from argp_parse, which we * know is a pointer to our arguments structure. */ ssh_bind sshbind = state->input; switch (key) { case 'p': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); port = atoi(arg); break; case 'd': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg); break; case 'k': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); break; case 'r': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg); break; case 'v': ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); break; case ARGP_KEY_ARG: if (state->arg_num >= 1) { /* Too many arguments. */ argp_usage (state); } ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); break; case ARGP_KEY_END: if (state->arg_num < 1) { /* Not enough arguments. */ argp_usage (state); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } /* Our argp parser. */ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; #endif /* HAVE_ARGP_H */ static int authenticate(ssh_session session) { ssh_message message; 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))){ ssh_message_auth_reply_success(message,0); ssh_message_free(message); return 1; } ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); // not authenticated, send default message ssh_message_reply_default(message); break; case SSH_AUTH_METHOD_NONE: default: printf("User %s wants to auth with unknown auth %d\n", ssh_message_auth_user(message), ssh_message_subtype(message)); ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); break; } break; default: ssh_message_auth_set_methods(message, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE); ssh_message_reply_default(message); } ssh_message_free(message); } while (1); return 0; } static int copy_fd_to_chan(socket_t fd, int revents, void *userdata) { ssh_channel chan = (ssh_channel)userdata; char buf[2048]; int sz = 0; if(!chan) { close(fd); return -1; } if(revents & POLLIN) { sz = read(fd, buf, 2048); if(sz > 0) { ssh_channel_write(chan, buf, sz); } } if(revents & POLLHUP) { ssh_channel_close(chan); sz = -1; } return sz; } static int copy_chan_to_fd(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata) { int fd = *(int*)userdata; int sz; (void)session; (void)channel; (void)is_stderr; sz = write(fd, data, len); return sz; } static void chan_close(ssh_session session, ssh_channel channel, void *userdata) { int fd = *(int*)userdata; (void)session; (void)channel; close(fd); } int ssh_channel_pty_window_change_callback_test (ssh_session session, ssh_channel channel, int width, int height, int pxwidth, int pwheight, void *userdata){ printf("win size change\n"); return 1; } struct ssh_channel_callbacks_struct cb = { .channel_pty_window_change_function=ssh_channel_pty_window_change_callback_test, .channel_data_function = copy_chan_to_fd, .channel_eof_function = chan_close, .channel_close_function = chan_close, .userdata = NULL }; static int main_loop(ssh_channel chan) { ssh_session session = ssh_channel_get_session(chan); socket_t fd; struct termios *term = NULL; struct winsize *win = NULL; pid_t childpid; ssh_event event; short events; int rc; childpid = forkpty(&fd, NULL, term, win); if(childpid == 0) { execl("/bin/bash", "/bin/bash", (char *)NULL); abort(); } cb.userdata = &fd; ssh_callbacks_init(&cb); ssh_set_channel_callbacks(chan, &cb); events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; event = ssh_event_new(); if(event == NULL) { printf("Couldn't get a event\n"); return -1; } if(ssh_event_add_fd(event, fd, events, copy_fd_to_chan, chan) != SSH_OK) { printf("Couldn't add an fd to the event\n"); ssh_event_free(event); return -1; } if(ssh_event_add_session(event, session) != SSH_OK) { printf("Couldn't add the session to the event\n"); ssh_event_remove_fd(event, fd); ssh_event_free(event); return -1; } do { rc = ssh_event_dopoll(event, 1000); if (rc == SSH_ERROR){ fprintf(stderr, "Error : %s\n", ssh_get_error(session)); ssh_event_free(event); ssh_disconnect(session); return -1; } } while(!ssh_channel_is_closed(chan)); ssh_event_remove_fd(event, fd); ssh_event_remove_session(event, session); ssh_event_free(event); return 0; } int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_message message; ssh_channel chan=0; int auth=0; int shell=0; int r; sshbind=ssh_bind_new(); session=ssh_new(); ssh_bind_options_set(sshbind,SSH_BIND_OPTIONS_BINDPORT_STR,"2222"); 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"); #ifdef HAVE_ARGP_H /* * Parse our arguments; every option seen by parse_opt will * be reflected in arguments. */ // argp_parse (&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; #endif #ifdef WITH_PCAP set_pcap(session); #endif if(ssh_bind_listen(sshbind)<0){ printf("Error listening to socket: %s\n", ssh_get_error(sshbind)); return 1; } printf("Started sample libssh sshd on port %d\n", port); printf("You can login as the user %s with the password %s\n", SSHD_USER, SSHD_PASSWORD); 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_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); return 1; } /* proceed to authentication */ auth = authenticate(session); if(!auth){ printf("Authentication error: %s\n", ssh_get_error(session)); ssh_disconnect(session); return 1; } /* wait for a channel session */ do { message = ssh_message_get(session); if(message){ if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN && ssh_message_subtype(message) == SSH_CHANNEL_SESSION) { chan = ssh_message_channel_request_open_reply_accept(message); ssh_message_free(message); break; } else { ssh_message_reply_default(message); ssh_message_free(message); } } else { break; } } while(!chan); if(!chan) { printf("Error: cleint did not ask for a channel session (%s)\n", ssh_get_error(session)); ssh_finalize(); return 1; } /* wait for a shell */ do { message = ssh_message_get(session); if(message != NULL) { printf("-------------\n"); if(ssh_message_type(message) == SSH_REQUEST_CHANNEL) { if(ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) { shell = 1; ssh_message_channel_request_reply_success(message); ssh_message_free(message); break; } else if(ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_PTY) { ssh_message_channel_request_reply_success(message); ssh_message_free(message); continue; } } ssh_message_reply_default(message); ssh_message_free(message); } else { break; } } while(!shell); if(!shell) { printf("Error: No shell requested (%s)\n", ssh_get_error(session)); return 1; } printf("it works !\n"); main_loop(chan); ssh_disconnect(session); ssh_bind_free(sshbind); #ifdef WITH_PCAP cleanup_pcap(); #endif ssh_finalize(); return 0; } 2014-03-01 19:37 GMT+08:00 Audrius Butkevicius < audrius.butkevicius@xxxxxxxxxxxxxxxx>: > Since your program is a proxy, I think you might not be proxying the > window resize messages correctly (or maybe not proxying them at all). > > Resize messages are part of channel, but they are not passed to channel > data callback, as they have a separate callback. > > I think you might need to implement the window resize callback on the > server side, and pass the requests on the client side, but its hard to say > without seeing the code.
Re: for help | Audrius Butkevicius <audrius.butkevicius@xxxxxxxxxxxxxxxx> |
Re: for help | Audrius Butkevicius <audrius.butkevicius@xxxxxxxxxxxxxxxx> |