size_t free_server (SCM server) { struct server_data *server_data = _scm_to_server_data (server); ssh_bind_free (server_data->bind); return 0; }
int spatch() { ssh_session session = NULL; ssh_bind sshbind = NULL; sthreadList* list = NULL; int port = SERVER_PORT; sshbind=ssh_bind_new(); //session=ssh_new(); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port); 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; } printf("Server start on port %d\n", port); while(1) { session=ssh_new(); if (ssh_bind_accept(sshbind, session) == SSH_ERROR) { printf("Error accepting a connection: %s\n", ssh_get_error(sshbind)); ssh_free(session); } else { list = newNodeList(list, session); if (pthread_create(&(list->thread), NULL, (void*)NewSessionLoop, (void*)&(list->sesData)) != 0) { sthreadList* tmp; ssh_disconnect(session); ssh_free(session); tmp = list; list = list->next; free(tmp); } } } if (session) ssh_free(session); cleanList(list); ssh_bind_free(sshbind); ssh_finalize(); return 0; }
void tmate_ssh_server_main(struct tmate_session *session, const char *keys_dir, int port) { sigset_t sigchld_set; struct tmate_ssh_client *client = &session->ssh_client; ssh_bind bind; pid_t pid; signal(SIGSEGV, handle_sigsegv); signal(SIGCHLD, handle_sigchld); sigemptyset(&sigchld_set); sigaddset(&sigchld_set, SIGCHLD); sigprocmask(SIG_BLOCK, &sigchld_set, NULL); bind = prepare_ssh(keys_dir, port); for (;;) { client->session = ssh_new(); client->channel = NULL; client->winsize_pty.ws_col = 80; client->winsize_pty.ws_row = 24; if (!client->session) tmate_fatal("Cannot initialize session"); sigprocmask(SIG_UNBLOCK, &sigchld_set, NULL); if (ssh_bind_accept(bind, client->session) < 0) tmate_fatal("Error accepting connection: %s", ssh_get_error(bind)); sigprocmask(SIG_BLOCK, &sigchld_set, NULL); if (get_ip(ssh_get_fd(client->session), client->ip_address, sizeof(client->ip_address)) < 0) tmate_fatal("Error getting IP address from connection"); if ((pid = fork()) < 0) tmate_fatal("Can't fork"); if (pid) { tmate_info("Child spawned pid=%d, ip=%s", pid, client->ip_address); ssh_free(client->session); } else { ssh_bind_free(bind); session->session_token = "init"; client_bootstrap(session); } } }
// Listen for incoming SSH connections. // When a connection is established, write all data received to stdout. void server_pipe(char *host, int port) { ssh_bind b = ssh_bind_new(); ssh_session s = ssh_new(); ssh_bind_options_set(b, SSH_BIND_OPTIONS_BINDADDR, host); ssh_bind_options_set(b, SSH_BIND_OPTIONS_BINDPORT, &port); ssh_bind_options_set(b, SSH_BIND_OPTIONS_RSAKEY, "test-server-key"); ssh_bind_options_set(b, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "5"); if(ssh_bind_listen(b) < 0) session_error(b, "listen"); if(ssh_bind_accept(b, s) != SSH_OK) session_error(b, "accept"); if(ssh_accept(s) < 0) session_error(s, "handshake"); int state = SERVER_CONNECTED; while(1) { ssh_message m = ssh_message_get(s); if(m) { int type = ssh_message_type(m); int subtype = ssh_message_subtype(m); ssh_message_auth_set_methods(m, SSH_AUTH_METHOD_PUBLICKEY); server_handle_message(s, m, type, subtype, &state); ssh_message_free(m); if(state == SERVER_CLOSED) { ssh_disconnect(s); ssh_bind_free(b); ssh_finalize(); return; } } else { session_error(s, "session"); } } }
int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_message message; ssh_channel chan=0; char buf[2048]; 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"); #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; } 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; } 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"); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { ssh_channel_write(chan, buf, i); if (write(1,buf,i) < 0) { printf("error writing to buffer\n"); return 1; } } } while (i>0); ssh_disconnect(session); ssh_bind_free(sshbind); #ifdef WITH_PCAP cleanup_pcap(); #endif ssh_finalize(); return 0; }
static void test_ssh_channel_request_x11(void **state) { struct hostkey_state *h = (struct hostkey_state *)*state; int rc, event_rc; pthread_t client_pthread; ssh_bind sshbind; ssh_session server; ssh_event event; struct channel_data channel_data; struct ssh_channel_callbacks_struct channel_cb = { .userdata = &channel_data, .channel_x11_req_function = ssh_channel_x11_req }; struct ssh_server_callbacks_struct server_cb = { .userdata = &channel_cb, .auth_password_function = auth_password_accept, .channel_open_request_session_function = channel_open }; memset(&channel_data, 0, sizeof(channel_data)); ssh_callbacks_init(&channel_cb); ssh_callbacks_init(&server_cb); /* Create server */ sshbind = torture_ssh_bind("localhost", TEST_SERVER_PORT, h->key_type, h->hostkey_path); assert_non_null(sshbind); /* Get client to connect */ rc = pthread_create(&client_pthread, NULL, client_thread, NULL); assert_return_code(rc, errno); server = ssh_new(); assert_true(server != NULL); rc = ssh_bind_accept(sshbind, server); assert_int_equal(rc, SSH_OK); /* Handle client connection */ ssh_set_server_callbacks(server, &server_cb); rc = ssh_handle_key_exchange(server); assert_int_equal(rc, SSH_OK); event = ssh_event_new(); assert_true(event != NULL); ssh_event_add_session(event, server); event_rc = SSH_OK; while (!channel_data.req_seen && event_rc == SSH_OK) { event_rc = ssh_event_dopoll(event, -1); } /* Cleanup */ ssh_event_free(event); ssh_free(server); ssh_bind_free(sshbind); rc = pthread_join(client_pthread, NULL); assert_int_equal(rc, 0); assert_true(channel_data.req_seen); assert_int_equal(channel_data.screen_number, x11_screen_number); }
int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_message message; ssh_channel chan=0; char buf[2048]; int auth=0; int shell=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"); #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 || !authenticated) { 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) { if(ssh_message_type(message) == SSH_REQUEST_CHANNEL && ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) { shell = 1; ssh_message_channel_request_reply_success(message); ssh_message_free(message); break; } 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"); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { if(*buf == '' || *buf == '') break; if(i == 1 && *buf == '\r') ssh_channel_write(chan, "\r\n", 2); else ssh_channel_write(chan, buf, i); if (write(1,buf,i) < 0) { printf("error writing to buffer\n"); return 1; } } } while (i>0); ssh_channel_close(chan); ssh_disconnect(session); ssh_bind_free(sshbind); #ifdef WITH_PCAP cleanup_pcap(); #endif ssh_finalize(); return 0; }
static gint mock_ssh_server (const gchar *server_addr, gint server_port, const gchar *user, const gchar *password, gboolean multi_step) { char portname[16]; char addrname[16]; struct sockaddr_storage addr; socklen_t addrlen; ssh_bind sshbind; const char *msg; int r; gint rounds = 0; state.event = ssh_event_new (); if (state.event == NULL) g_return_val_if_reached (-1); sshbind = ssh_bind_new (); state.session = ssh_new (); if (server_addr == NULL) server_addr = "127.0.0.1"; ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_BINDADDR, server_addr); ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_BINDPORT, &server_port); ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_RSAKEY, SRCDIR "/src/ws/mock_rsa_key"); ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_DSAKEY, SRCDIR "/src/ws/mock_dsa_key"); if (ssh_bind_listen (sshbind) < 0) { g_critical ("couldn't listen on socket: %s", ssh_get_error (sshbind)); return 1; } state.bind_fd = ssh_bind_get_fd (sshbind); state.user = user; state.password = password; state.multi_step = multi_step; ssh_pki_import_pubkey_file (SRCDIR "/src/ws/test_rsa.pub", &state.pkey); state.buffer = g_byte_array_new (); /* Print out the port */ if (server_port == 0) { addrlen = sizeof (addr); if (getsockname (state.bind_fd, (struct sockaddr *)&addr, &addrlen) < 0) { g_critical ("couldn't get local address: %s", g_strerror (errno)); return 1; } r = getnameinfo ((struct sockaddr *)&addr, addrlen, addrname, sizeof (addrname), portname, sizeof (portname), NI_NUMERICHOST | NI_NUMERICSERV); if (r != 0) { g_critical ("couldn't get local port: %s", gai_strerror (r)); return 1; } /* Caller wants to know the port */ g_print ("%s\n", portname); } /* Close stdout (once above info is printed) */ close (1); ssh_set_message_callback (state.session, authenticate_callback, &rounds); r = ssh_bind_accept (sshbind, state.session); if (r == SSH_ERROR) { g_critical ("accepting connection failed: %s", ssh_get_error (sshbind)); return 1; } state.session_fd = ssh_get_fd (state.session); if (ssh_handle_key_exchange (state.session)) { msg = ssh_get_error (state.session); if (!strstr (msg, "_DISCONNECT")) g_critical ("key exchange failed: %s", msg); return 1; } if (ssh_event_add_session (state.event, state.session) != SSH_OK) g_return_val_if_reached (-1); do { ssh_event_dopoll (state.event, 10000); } while (ssh_is_connected (state.session)); ssh_event_remove_session (state.event, state.session); ssh_event_free (state.event); ssh_free (state.session); ssh_key_free (state.pkey); g_byte_array_free (state.buffer, TRUE); ssh_bind_free (sshbind); return 0; }
static int pkd_exec_hello(int fd, struct pkd_daemon_args *args) { int rc = -1; ssh_bind b = NULL; ssh_session s = NULL; ssh_event e = NULL; ssh_channel c = NULL; enum ssh_bind_options_e opts = -1; int level = args->opts.libssh_log_level; enum pkd_hostkey_type_e type = args->type; const char *hostkeypath = args->hostkeypath; pkd_state.eof_received = 0; pkd_state.close_received = 0; pkd_state.req_exec_received = 0; b = ssh_bind_new(); if (b == NULL) { pkderr("ssh_bind_new\n"); goto outclose; } if (type == PKD_RSA) { opts = SSH_BIND_OPTIONS_RSAKEY; } else if (type == PKD_ED25519) { opts = SSH_BIND_OPTIONS_HOSTKEY; #ifdef HAVE_DSA } else if (type == PKD_DSA) { opts = SSH_BIND_OPTIONS_DSAKEY; #endif } else if (type == PKD_ECDSA) { opts = SSH_BIND_OPTIONS_ECDSAKEY; } else { pkderr("unknown kex algorithm: %d\n", type); rc = -1; goto outclose; } rc = ssh_bind_options_set(b, opts, hostkeypath); if (rc != 0) { pkderr("ssh_bind_options_set: %s\n", ssh_get_error(b)); goto outclose; } rc = ssh_bind_options_set(b, SSH_BIND_OPTIONS_LOG_VERBOSITY, &level); if (rc != 0) { pkderr("ssh_bind_options_set log verbosity: %s\n", ssh_get_error(b)); goto outclose; } s = ssh_new(); if (s == NULL) { pkderr("ssh_new\n"); goto outclose; } /* * ssh_bind_accept loads host key as side-effect. If this * succeeds, the given 'fd' will be closed upon 'ssh_free(s)'. */ rc = ssh_bind_accept_fd(b, s, fd); if (rc != SSH_OK) { pkderr("ssh_bind_accept_fd: %s\n", ssh_get_error(b)); goto outclose; } /* accept only publickey-based auth */ ssh_set_auth_methods(s, SSH_AUTH_METHOD_PUBLICKEY); /* initialize callbacks */ ssh_callbacks_init(&pkd_server_cb); pkd_server_cb.userdata = &c; rc = ssh_set_server_callbacks(s, &pkd_server_cb); if (rc != SSH_OK) { pkderr("ssh_set_server_callbacks: %s\n", ssh_get_error(s)); goto out; } /* first do key exchange */ rc = ssh_handle_key_exchange(s); if (rc != SSH_OK) { pkderr("ssh_handle_key_exchange: %s\n", ssh_get_error(s)); goto out; } /* setup and pump event to carry out exec channel */ e = ssh_event_new(); if (e == NULL) { pkderr("ssh_event_new\n"); goto out; } rc = ssh_event_add_session(e, s); if (rc != SSH_OK) { pkderr("ssh_event_add_session\n"); goto out; } /* poll until exec channel established */ while ((ctx.keep_going != 0) && (rc != SSH_ERROR) && (pkd_state.req_exec_received == 0)) { rc = ssh_event_dopoll(e, -1 /* infinite timeout */); } if (rc == SSH_ERROR) { pkderr("ssh_event_dopoll\n"); goto out; } else if (c == NULL) { pkderr("poll loop exited but exec channel not ready\n"); rc = -1; goto out; } rc = ssh_channel_write(c, "hello\n", 6); /* XXX: customizable payloads */ if (rc != 6) { pkderr("ssh_channel_write partial (%d)\n", rc); } rc = ssh_channel_request_send_exit_status(c, 0); if (rc != SSH_OK) { pkderr("ssh_channel_request_send_exit_status: %s\n", ssh_get_error(s)); goto out; } rc = ssh_channel_send_eof(c); if (rc != SSH_OK) { pkderr("ssh_channel_send_eof: %s\n", ssh_get_error(s)); goto out; } rc = ssh_channel_close(c); if (rc != SSH_OK) { pkderr("ssh_channel_close: %s\n", ssh_get_error(s)); goto out; } while ((ctx.keep_going != 0) && (pkd_state.eof_received == 0) && (pkd_state.close_received == 0)) { rc = ssh_event_dopoll(e, 1000 /* milliseconds */); if (rc == SSH_ERROR) { /* log, but don't consider this fatal */ pkdout("ssh_event_dopoll for eof + close: %s\n", ssh_get_error(s)); rc = 0; break; } else { rc = 0; } } while ((ctx.keep_going != 0) && (ssh_is_connected(s))) { rc = ssh_event_dopoll(e, 1000 /* milliseconds */); if (rc == SSH_ERROR) { /* log, but don't consider this fatal */ pkdout("ssh_event_dopoll for session connection: %s\n", ssh_get_error(s)); rc = 0; break; } else { rc = 0; } } goto out; outclose: close(fd); out: if (c != NULL) { ssh_channel_free(c); } if (e != NULL) { ssh_event_remove_session(e, s); ssh_event_free(e); } if (s != NULL) { ssh_disconnect(s); ssh_free(s); } if (b != NULL) { ssh_bind_free(b); } return rc; }
static void handle_session(ssh_event event, ssh_session session) { int n; int rc = 0; /* Structure for storing the pty size. */ struct winsize wsize = { .ws_row = 0, .ws_col = 0, .ws_xpixel = 0, .ws_ypixel = 0 }; /* Our struct holding information about the channel. */ struct channel_data_struct cdata = { .pid = 0, .pty_master = -1, .pty_slave = -1, .child_stdin = -1, .child_stdout = -1, .child_stderr = -1, .event = NULL, .winsize = &wsize }; /* Our struct holding information about the session. */ struct session_data_struct sdata = { .channel = NULL, .auth_attempts = 0, .authenticated = 0 }; struct ssh_channel_callbacks_struct channel_cb = { .userdata = &cdata, .channel_pty_request_function = pty_request, .channel_pty_window_change_function = pty_resize, .channel_shell_request_function = shell_request, .channel_exec_request_function = exec_request, .channel_data_function = data_function, .channel_subsystem_request_function = subsystem_request }; struct ssh_server_callbacks_struct server_cb = { .userdata = &sdata, .auth_password_function = auth_password, .channel_open_request_session_function = channel_open, }; if (authorizedkeys[0]) { server_cb.auth_pubkey_function = auth_publickey; ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY); } else ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD); ssh_callbacks_init(&server_cb); ssh_callbacks_init(&channel_cb); ssh_set_server_callbacks(session, &server_cb); if (ssh_handle_key_exchange(session) != SSH_OK) { fprintf(stderr, "%s\n", ssh_get_error(session)); return; } ssh_event_add_session(event, session); n = 0; while (sdata.authenticated == 0 || sdata.channel == NULL) { /* If the user has used up all attempts, or if he hasn't been able to * authenticate in 10 seconds (n * 100ms), disconnect. */ if (sdata.auth_attempts >= 3 || n >= 100) { return; } if (ssh_event_dopoll(event, 100) == SSH_ERROR) { fprintf(stderr, "%s\n", ssh_get_error(session)); return; } n++; } ssh_set_channel_callbacks(sdata.channel, &channel_cb); do { /* Poll the main event which takes care of the session, the channel and * even our child process's stdout/stderr (once it's started). */ if (ssh_event_dopoll(event, -1) == SSH_ERROR) { ssh_channel_close(sdata.channel); } /* If child process's stdout/stderr has been registered with the event, * or the child process hasn't started yet, continue. */ if (cdata.event != NULL || cdata.pid == 0) { continue; } /* Executed only once, once the child process starts. */ cdata.event = event; /* If stdout valid, add stdout to be monitored by the poll event. */ if (cdata.child_stdout != -1) { if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stdout to poll context\n"); ssh_channel_close(sdata.channel); } } /* If stderr valid, add stderr to be monitored by the poll event. */ if (cdata.child_stderr != -1){ if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr, sdata.channel) != SSH_OK) { fprintf(stderr, "Failed to register stderr to poll context\n"); ssh_channel_close(sdata.channel); } } } while(ssh_channel_is_open(sdata.channel) && (cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0)); close(cdata.pty_master); close(cdata.child_stdin); close(cdata.child_stdout); close(cdata.child_stderr); /* Remove the descriptors from the polling context, since they are now * closed, they will always trigger during the poll calls. */ ssh_event_remove_fd(event, cdata.child_stdout); ssh_event_remove_fd(event, cdata.child_stderr); /* If the child process exited. */ if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) { rc = WEXITSTATUS(rc); ssh_channel_request_send_exit_status(sdata.channel, rc); /* If client terminated the channel or the process did not exit nicely, * but only if something has been forked. */ } else if (cdata.pid > 0) { kill(cdata.pid, SIGKILL); } ssh_channel_send_eof(sdata.channel); ssh_channel_close(sdata.channel); /* Wait up to 5 seconds for the client to terminate the session. */ for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) { ssh_event_dopoll(event, 100); } } /* SIGCHLD handler for cleaning up dead children. */ static void sigchld_handler(int signo) { (void) signo; while (waitpid(-1, NULL, WNOHANG) > 0); } int main(int argc, char **argv) { ssh_bind sshbind; ssh_session session; ssh_event event; struct sigaction sa; int rc; /* Set up SIGCHLD handler. */ sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; if (sigaction(SIGCHLD, &sa, NULL) != 0) { fprintf(stderr, "Failed to register SIGCHLD handler\n"); return 1; } rc = ssh_init(); if (rc < 0) { fprintf(stderr, "ssh_init failed\n"); return 1; } sshbind = ssh_bind_new(); if (sshbind == NULL) { fprintf(stderr, "ssh_bind_new failed\n"); return 1; } #ifdef HAVE_ARGP_H argp_parse(&argp, argc, argv, 0, 0, sshbind); #else (void) argc; (void) argv; set_default_keys(sshbind, 0, 0, 0); #endif /* HAVE_ARGP_H */ if(ssh_bind_listen(sshbind) < 0) { fprintf(stderr, "%s\n", ssh_get_error(sshbind)); return 1; } while (1) { session = ssh_new(); if (session == NULL) { fprintf(stderr, "Failed to allocate session\n"); continue; } /* Blocks until there is a new incoming connection. */ if(ssh_bind_accept(sshbind, session) != SSH_ERROR) { switch(fork()) { case 0: /* Remove the SIGCHLD handler inherited from parent. */ sa.sa_handler = SIG_DFL; sigaction(SIGCHLD, &sa, NULL); /* Remove socket binding, which allows us to restart the * parent process, without terminating existing sessions. */ ssh_bind_free(sshbind); event = ssh_event_new(); if (event != NULL) { /* Blocks until the SSH session ends by either * child process exiting, or client disconnecting. */ handle_session(event, session); ssh_event_free(event); } else { fprintf(stderr, "Could not create polling context\n"); } ssh_disconnect(session); ssh_free(session); exit(0); case -1: fprintf(stderr, "Failed to fork\n"); } } else { fprintf(stderr, "%s\n", ssh_get_error(sshbind)); } /* Since the session has been passed to a child fork, do some cleaning * up at the parent process. */ ssh_disconnect(session); ssh_free(session); } ssh_bind_free(sshbind); ssh_finalize(); return 0; }
void listen_loop(int do_init) { struct client_struct* new_client; struct np_sock npsock = {.count = 0}; int ret; struct timespec ts; #ifdef NP_SSH ssh_bind sshbind = NULL; #endif #ifdef NP_TLS SSL_CTX* tlsctx = NULL; #endif /* Init */ if (do_init) { #ifdef NP_SSH np_ssh_init(); #endif #ifdef NP_TLS np_tls_init(); #endif if ((ret = pthread_create(&netopeer_state.data_tid, NULL, data_thread, NULL)) != 0) { nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret)); return; } if ((ret = pthread_create(&netopeer_state.netconf_rpc_tid, NULL, netconf_rpc_thread, NULL)) != 0) { nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret)); return; } } /* Main accept loop */ do { new_client = NULL; /* Binds change check */ if (netopeer_options.binds_change_flag) { /* BINDS LOCK */ pthread_mutex_lock(&netopeer_options.binds_lock); sock_cleanup(&npsock); sock_listen(netopeer_options.binds, &npsock); netopeer_options.binds_change_flag = 0; /* BINDS UNLOCK */ pthread_mutex_unlock(&netopeer_options.binds_lock); if (npsock.count == 0) { nc_verb_warning("Server is not listening on any address!"); } } #ifdef NP_SSH sshbind = np_ssh_server_id_check(sshbind); #endif #ifdef NP_TLS tlsctx = np_tls_server_id_check(tlsctx); #endif #ifndef DISABLE_CALLHOME /* Callhome client check */ if (callhome_client != NULL) { /* CALLHOME LOCK */ pthread_mutex_lock(&callhome_lock); new_client = callhome_client; callhome_client = NULL; /* CALLHOME UNLOCK */ pthread_mutex_unlock(&callhome_lock); } #endif /* Listen client check */ if (new_client == NULL) { new_client = sock_accept(&npsock); } /* New client full structure creation */ if (new_client != NULL) { /* Maximum number of sessions check */ if (netopeer_options.max_sessions > 0) { ret = 0; #ifdef NP_SSH ret += np_ssh_session_count(); #endif #ifdef NP_TLS ret += np_tls_session_count(); #endif if (ret >= netopeer_options.max_sessions) { nc_verb_error("Maximum number of sessions reached, droppping the new client."); new_client->to_free = 1; switch (new_client->transport) { #ifdef NP_SSH case NC_TRANSPORT_SSH: client_free_ssh((struct client_struct_ssh*)new_client); break; #endif #ifdef NP_TLS case NC_TRANSPORT_TLS: client_free_tls((struct client_struct_tls*)new_client); break; #endif default: nc_verb_error("%s: internal error (%s:%d)", __func__, __FILE__, __LINE__); } free(new_client); /* sleep to prevent clients from immediate connection retry */ usleep(netopeer_options.response_time*1000); continue; } } switch (new_client->transport) { #ifdef NP_SSH case NC_TRANSPORT_SSH: ret = np_ssh_create_client((struct client_struct_ssh*)new_client, sshbind); if (ret != 0) { new_client->to_free = 1; client_free_ssh((struct client_struct_ssh*)new_client); } break; #endif #ifdef NP_TLS case NC_TRANSPORT_TLS: ret = np_tls_create_client((struct client_struct_tls*)new_client, tlsctx); if (ret != 0) { new_client->to_free = 1; client_free_tls((struct client_struct_tls*)new_client); } break; #endif default: nc_verb_error("Client with an unknown transport protocol, dropping it."); new_client->to_free = 1; ret = 1; } /* client is not valid, some error occured */ if (ret != 0) { free(new_client); continue; } /* add the client into the global clients structure */ /* GLOBAL WRITE LOCK */ pthread_rwlock_wrlock(&netopeer_state.global_lock); client_append(&netopeer_state.clients, new_client); /* GLOBAL WRITE UNLOCK */ pthread_rwlock_unlock(&netopeer_state.global_lock); } } while (!quit && !restart_soft); /* Cleanup */ sock_cleanup(&npsock); #ifdef NP_SSH ssh_bind_free(sshbind); #endif #ifdef NP_TLS SSL_CTX_free(tlsctx); #endif if (!restart_soft) { if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { nc_verb_warning("%s: failed to get time (%s)", strerror(errno)); } ts.tv_sec += THREAD_JOIN_QUIT_TIMEOUT; /* wait for all the clients to exit nicely themselves */ if ((ret = pthread_timedjoin_np(netopeer_state.netconf_rpc_tid, NULL, &ts)) != 0) { nc_verb_warning("%s: failed to join the netconf RPC thread (%s)", __func__, strerror(ret)); if (ret == ETIMEDOUT) { pthread_cancel(netopeer_state.netconf_rpc_tid); } } if ((ret = pthread_timedjoin_np(netopeer_state.data_tid, NULL, &ts)) != 0) { nc_verb_warning("%s: failed to join the SSH data thread (%s)", __func__, strerror(ret)); if (ret == ETIMEDOUT) { pthread_cancel(netopeer_state.data_tid); } } #ifdef NP_SSH np_ssh_cleanup(); #endif #ifdef NP_TLS np_tls_cleanup(); #endif } } int main(int argc, char** argv) { struct sigaction action; sigset_t block_mask; char *aux_string = NULL, path[PATH_MAX]; int next_option; int daemonize = 0, len; int listen_init = 1; struct np_module* netopeer_module = NULL, *server_module = NULL; /* initialize message system and set verbose and debug variables */ if ((aux_string = getenv(ENVIRONMENT_VERBOSE)) == NULL) { netopeer_options.verbose = NC_VERB_ERROR; } else { netopeer_options.verbose = atoi(aux_string); } aux_string = NULL; /* for sure to avoid unwanted changes in environment */ /* parse given options */ while ((next_option = getopt(argc, argv, OPTSTRING)) != -1) { switch (next_option) { case 'd': daemonize = 1; break; case 'h': print_usage(argv[0]); break; case 'v': netopeer_options.verbose = atoi(optarg); break; case 'V': print_version(argv[0]); break; default: print_usage(argv[0]); break; } } /* set signal handler */ sigfillset (&block_mask); action.sa_handler = signal_handler; action.sa_mask = block_mask; action.sa_flags = 0; sigaction(SIGINT, &action, NULL); sigaction(SIGQUIT, &action, NULL); sigaction(SIGABRT, &action, NULL); sigaction(SIGTERM, &action, NULL); sigaction(SIGHUP, &action, NULL); nc_callback_print(clb_print); /* normalize value if not from the enum */ if (netopeer_options.verbose > NC_VERB_DEBUG) { netopeer_options.verbose = NC_VERB_DEBUG; } nc_verbosity(netopeer_options.verbose); /* go to the background as a daemon */ if (daemonize == 1) { if (daemon(0, 0) != 0) { nc_verb_error("Going to background failed (%s)", strerror(errno)); return EXIT_FAILURE; } openlog("netopeer-server", LOG_PID, LOG_DAEMON); } else { openlog("netopeer-server", LOG_PID|LOG_PERROR, LOG_DAEMON); } /* make sure we were executed by root */ if (geteuid() != 0) { nc_verb_error("Failed to start, must have root privileges."); return EXIT_FAILURE; } /* * this initialize the library and check potential ABI mismatches * between the version it was compiled for and the actual shared * library used. */ LIBXML_TEST_VERSION /* initialize library including internal datastores and maybee something more */ if (nc_init(NC_INIT_ALL | NC_INIT_MULTILAYER) < 0) { nc_verb_error("Library initialization failed."); return EXIT_FAILURE; } server_start = 1; restart: /* start NETCONF server module */ if ((server_module = calloc(1, sizeof(struct np_module))) == NULL) { nc_verb_error("Creating necessary NETCONF server plugin failed!"); return EXIT_FAILURE; } server_module->name = strdup(NCSERVER_MODULE_NAME); if (module_enable(server_module, 0)) { nc_verb_error("Starting necessary NETCONF server plugin failed!"); free(server_module->name); free(server_module); return EXIT_FAILURE; } /* start netopeer device module - it will start all modules that are * in its configuration and in server configuration */ if ((netopeer_module = calloc(1, sizeof(struct np_module))) == NULL) { nc_verb_error("Creating necessary Netopeer plugin failed!"); module_disable(server_module, 1); return EXIT_FAILURE; } netopeer_module->name = strdup(NETOPEER_MODULE_NAME); if (module_enable(netopeer_module, 0)) { nc_verb_error("Starting necessary Netopeer plugin failed!"); module_disable(server_module, 1); free(netopeer_module->name); free(netopeer_module); return EXIT_FAILURE; } server_start = 0; nc_verb_verbose("Netopeer server successfully initialized."); listen_loop(listen_init); /* unload Netopeer module -> unload all modules */ module_disable(server_module, 1); module_disable(netopeer_module, 1); /* main cleanup */ if (!restart_soft) { /* close libnetconf only when shutting down or hard restarting the server */ nc_close(); } if (restart_soft) { nc_verb_verbose("Server is going to soft restart."); restart_soft = 0; listen_init = 0; goto restart; } else if (restart_hard) { nc_verb_verbose("Server is going to hard restart."); len = readlink("/proc/self/exe", path, PATH_MAX); path[len] = 0; xmlCleanupParser(); execv(path, argv); } /* *Free the global variables that may *have been allocated by the parser. */ xmlCleanupParser(); return EXIT_SUCCESS; }
int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; ssh_event mainloop; struct ssh_server_callbacks_struct cb = { .userdata = NULL, .auth_password_function = auth_password, .auth_gssapi_mic_function = auth_gssapi_mic, .channel_open_request_session_function = new_session_channel }; char buf[2048]; 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"); #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 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; } ssh_callbacks_init(&cb); ssh_set_server_callbacks(session, &cb); if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); return 1; } ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); mainloop = ssh_event_new(); ssh_event_add_session(mainloop, session); while (!(authenticated && chan != NULL)){ if(error) break; r = ssh_event_dopoll(mainloop, -1); if (r == SSH_ERROR){ printf("Error : %s\n",ssh_get_error(session)); ssh_disconnect(session); return 1; } } if(error){ printf("Error, exiting loop\n"); } else printf("Authenticated and got a channel\n"); do{ i=ssh_channel_read(chan,buf, 2048, 0); if(i>0) { ssh_channel_write(chan, buf, i); if (write(1,buf,i) < 0) { printf("error writing to buffer\n"); return 1; } if (buf[0] == '\x0d') { if (write(1, "\n", 1) < 0) { printf("error writing to buffer\n"); return 1; } ssh_channel_write(chan, "\n", 1); } } } while (i>0); ssh_disconnect(session); ssh_bind_free(sshbind); ssh_finalize(); return 0; }
int main(int argc, char **argv){ ssh_session session; ssh_bind sshbind; struct ssh_server_callbacks_struct cb = { .userdata = NULL, .auth_password_function = auth_password, .auth_gssapi_mic_function = auth_gssapi_mic, .channel_open_request_session_function = new_session_channel, .service_request_function = service_request }; struct ssh_callbacks_struct cb_gen = { .userdata = NULL, .global_request_function = global_request }; int ret = 1; sshbind = ssh_bind_new(); session = ssh_new(); mainloop = ssh_event_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"); #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 if (ssh_bind_listen(sshbind) < 0) { printf("Error listening to socket: %s\n", ssh_get_error(sshbind)); return 1; } if (ssh_bind_accept(sshbind, session) == SSH_ERROR) { printf("error accepting a connection : %s\n", ssh_get_error(sshbind)); ret = 1; goto shutdown; } ssh_callbacks_init(&cb); ssh_callbacks_init(&cb_gen); ssh_set_server_callbacks(session, &cb); ssh_set_callbacks(session, &cb_gen); ssh_set_message_callback(session, message_callback, (void *)NULL); if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); ret = 1; goto shutdown; } ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); ssh_event_add_session(mainloop, session); while (!authenticated) { if (error_set) { break; } if (ssh_event_dopoll(mainloop, -1) == SSH_ERROR) { printf("Error : %s\n", ssh_get_error(session)); ret = 1; goto shutdown; } } if (error_set) { printf("Error, exiting loop\n"); } else { printf("Authenticated and got a channel\n"); while (!error_set) { if (ssh_event_dopoll(mainloop, 100) == SSH_ERROR) { printf("Error : %s\n", ssh_get_error(session)); ret = 1; goto shutdown; } do_cleanup(&cleanup_stack); } } shutdown: ssh_disconnect(session); ssh_bind_free(sshbind); ssh_finalize(); return ret; }
/* SIGINT handler. Cleanup the ssh* objects and exit. */ static void wrapup(void) { ssh_disconnect(session); ssh_bind_free(sshbind); ssh_finalize(); exit(0); }
int main(int argc, char **argv){ SSH_OPTIONS *options=ssh_options_new(); SSH_SESSION *session; SSH_BIND *ssh_bind; CHANNEL *chan=NULL; SFTP_SESSION *sftp=NULL; int ret; int donotfork=0; char *config="mercurius.conf"; ssh_options_getopt(options,&argc,argv); while((ret=getopt(argc, argv, "Df:"))!=-1){ switch(ret){ case 'D': donotfork=1; break; case 'f': config=strdup(optarg); break; case '?': usage(argv[0]); exit(1); } } if(optind<argc) { usage(argv[0]); exit(1); } ret=parse_config(config); if(ret != 0){ printf("Error parsing configuration file\n"); return 1; } if(!rsa && !dsa){ printf("There must be at least one RSA or DSA host key\n"); return 1; } if(dsa) ssh_options_set_dsa_server_key(options,dsa); if(rsa) ssh_options_set_rsa_server_key(options,rsa); //printf("port : %d\n",port); if(port!=0) ssh_options_set_port(options,port); ssh_bind=ssh_bind_new(); ssh_bind_set_options(ssh_bind,options); if(ssh_bind_listen(ssh_bind)<0){ printf("Error listening to socket: %s\n",ssh_get_error(ssh_bind)); return 1; } signal(SIGCHLD,SIG_IGN); if(!donotfork){ ssh_say(1,"Going into background...\n"); if(fork()){ exit(0); } } while(1){ session=ssh_bind_accept(ssh_bind); if(!session){ printf("error accepting a connection : %s\n",ssh_get_error(ssh_bind)); return 1; } if(fork()==0){ break; } ssh_silent_disconnect(session); } ssh_bind_free(ssh_bind); //printf("Socket connected : %d\n",ssh_get_fd(session)); if(ssh_accept(session)){ printf("ssh_accept : %s\n",ssh_get_error(session)); return 1; } if(do_auth(session)<0){ printf("error : %s\n",ssh_get_error(session)); return 1; } ssh_say(1,"user authenticated\n"); chan=recv_channel(session); if(!chan){ printf("error : %s\n",ssh_get_error(session)); return 1; } sftp=sftp_server_new(session,chan); if(sftp_server_init(sftp)){ printf("error : %s\n",ssh_get_error(session)); return 1; } ssh_say(1,"Sftp session open by client\n"); sftploop(session,sftp); ssh_say(1,"Client disconnected\n"); ssh_disconnect(session); return 0; }