コード例 #1
0
ファイル: session.c プロジェクト: darknightghost/mcserverd
void session_free(psession_t p_session)
{
	if(p_session->channel != NULL) {
		ssh_channel_free(p_session->channel);
	}

	ssh_event_free(p_session->event);
	ssh_free(p_session->session);
	free(p_session);

	return;
}
コード例 #2
0
ファイル: ssh_main.c プロジェクト: metallistov20/convinject-1
static void select_loop(ssh_session session,ssh_channel channel)
{
ssh_connector connector_in, connector_out, connector_err;

	ssh_event event = ssh_event_new();

	/* stdin */
	connector_in = ssh_connector_new(session);
	ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDOUT);
	/* Attach first endpointg of input pipe to SSH core */
	ssh_connector_set_in_fd(connector_in, input_pipe[0] /* 0 */);
	ssh_event_add_connector(event, connector_in);

	/* stdout */
	connector_out = ssh_connector_new(session);

#if defined(OUT_PIPE)
	/* Attach first endpointg of output pipe to SSH core */
	ssh_connector_set_out_fd(connector_out,  output_pipe[0] /* 1*/);
#else
	ssh_connector_set_out_fd(connector_out,  1);
#endif /* OUT_PIPE */

	ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDOUT);
	ssh_event_add_connector(event, connector_out);

	/* stderr */
	connector_err = ssh_connector_new(session);
	ssh_connector_set_out_fd(connector_err, 2);
	ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
	ssh_event_add_connector(event, connector_err);

	while(ssh_channel_is_open(channel))
	{
		if(signal_delayed)

		    sizechanged();

		ssh_event_dopoll(event, 60000);
	}

	ssh_event_remove_connector(event, connector_in);
	ssh_event_remove_connector(event, connector_out);
	ssh_event_remove_connector(event, connector_err);

	ssh_connector_free(connector_in);
	ssh_connector_free(connector_out);
	ssh_connector_free(connector_err);

	ssh_event_free(event);
	ssh_channel_free(channel);
}
コード例 #3
0
ファイル: samplesshd-tty.c プロジェクト: FuckingCoder/libssh
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;


    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");
        return -1;
    }
    if(ssh_event_add_session(event, session) != SSH_OK) {
        printf("Couldn't add the session to the event\n");
        return -1;
    }

    do {
        ssh_event_dopoll(event, 1000);
    } while(!ssh_channel_is_closed(chan));

    ssh_event_remove_fd(event, fd);

    ssh_event_remove_session(event, session);

    ssh_event_free(event);
    return 0;
}
コード例 #4
0
ファイル: cockpitsshtransport.c プロジェクト: leospol/cockpit
static void
cockpit_ssh_transport_finalize (GObject *object)
{
  CockpitSshTransport *self = COCKPIT_SSH_TRANSPORT (object);

  /* libssh channels like to hang around even after they're freed */
  memset (&self->channel_cbs, 0, sizeof (self->channel_cbs));
  ssh_event_free (self->event);

  cockpit_ssh_data_free (self->data);
  g_free (self->logname);

  g_queue_free_full (self->queue, (GDestroyNotify)g_bytes_unref);
  g_byte_array_free (self->buffer, TRUE);

  g_assert (self->io == NULL);

  G_OBJECT_CLASS (cockpit_ssh_transport_parent_class)->finalize (object);
}
コード例 #5
0
ファイル: torture_server_x11.c プロジェクト: codinn/libssh
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);
}
コード例 #6
0
ファイル: mock-sshd.c プロジェクト: arilivigni/cockpit
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;
}
コード例 #7
0
ファイル: connect.c プロジェクト: chrisdew/node-libssh
/**
 * @brief A wrapper for the select syscall
 *
 * This functions acts more or less like the select(2) syscall.\n
 * There is no support for writing or exceptions.\n
 *
 * @param[in]  channels Arrays of channels pointers terminated by a NULL.
 *                      It is never rewritten.
 *
 * @param[out] outchannels Arrays of same size that "channels", there is no need
 *                         to initialize it.
 *
 * @param[in]  maxfd    Maximum +1 file descriptor from readfds.
 *
 * @param[in]  readfds  A fd_set of file descriptors to be select'ed for
 *                      reading.
 *
 * @param[in]  timeout  A timeout for the select.
 *
 * @return              SSH_OK on success,
 *                      SSH_ERROR on error,
 *                      SSH_EINTR if it was interrupted. In that case,
 *                      just restart it.
 *
 * @warning libssh is not reentrant here. That means that if a signal is caught
 *          during the processing of this function, you cannot call libssh
 *          functions on sessions that are busy with ssh_select().
 *
 * @see select(2)
 */
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
    fd_set *readfds, struct timeval *timeout) {
  fd_set origfds;
  socket_t fd;
  int i,j;
  int rc;
  int base_tm, tm;
  struct ssh_timestamp ts;
  ssh_event event = ssh_event_new();
  int firstround=1;

  base_tm = tm=timeout->tv_sec * 1000 + timeout->tv_usec/1000;
  for (i=0 ; channels[i] != NULL; ++i){
    ssh_event_add_session(event, channels[i]->session);
  }

  FD_ZERO(&origfds);
  for (fd = 0; fd < maxfd ; fd++) {
      if (FD_ISSET(fd, readfds)) {
          ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
          FD_SET(fd, &origfds);
      }
  }
  outchannels[0] = NULL;
  FD_ZERO(readfds);
  ssh_timestamp_init(&ts);
  do {
    /* Poll every channel */
    j = 0;
    for (i = 0; channels[i]; i++) {
      if(ssh_channel_poll(channels[i], 0) != 0) {
        outchannels[j] = channels[i];
        j++;
      } else if(ssh_channel_poll(channels[i], 1) != 0) {
        outchannels[j] = channels[i];
        j++;
      }
    }
    outchannels[j] = NULL;
    if(j != 0)
      break;
    /* watch if a user socket was triggered */
    for (fd = 0; fd < maxfd; fd++) {
        if (FD_ISSET(fd, readfds)) {
            goto out;
        }
    }

    /* If the timeout is elapsed, we should go out */
    if(!firstround && ssh_timeout_elapsed(&ts, base_tm))
      goto out;
    /* since there's nothing, let's fire the polling */
    rc = ssh_event_dopoll(event,tm);
    if (rc == SSH_ERROR){
      goto out;
    }
    tm = ssh_timeout_update(&ts, base_tm);
    firstround=0;
  } while (1);
out:
  for (fd = 0; fd < maxfd; fd++) {
    if (FD_ISSET(fd, &origfds)) {
      ssh_event_remove_fd(event, fd);
    }
  }
  ssh_event_free(event);
  return SSH_OK;
}
コード例 #8
0
ファイル: pkd_daemon.c プロジェクト: ShiftMediaProject/libssh
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;
}
コード例 #9
0
ファイル: ssh_server_fork.c プロジェクト: cedral/libssh
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;
}
コード例 #10
0
ファイル: ssh_server.c プロジェクト: seem8/friendup
int SSHThread( void *data )
{
	// TODO: Hogne was here, disabling this problem child.. :)
	return 0;
#ifdef ENABLE_SSH	
	ssh_session session = NULL;
	ssh_bind sshbind = NULL;
	
	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 i;
	int r;
	
	DEBUG("Starting SSH Process\n");
	
	SSHServer *ts = (SSHServer *)data;
	if( !ts ) return 0;

	ts->sshs_FriendHome = getenv( "FRIEND_HOME" );
		
	int len = strlen( ts->sshs_FriendHome );
	ts->sshs_RSAKeyHome = calloc( len+64, sizeof(char) );
	ts->sshs_DSAKeyHome = calloc( len+64, sizeof(char) );
		
	strcpy( ts->sshs_RSAKeyHome, ts->sshs_FriendHome );
	strcpy( ts->sshs_DSAKeyHome, ts->sshs_FriendHome );
	strcat( ts->sshs_RSAKeyHome, "keys/ssh_host_rsa_key" );
	strcat( ts->sshs_DSAKeyHome, "keys/ssh_host_dsa_key" );
	
	//DEBUG("SSH sshs_RSAKeyHome set to %s\n", ts->sshs_RSAKeyHome );
		
	sshbind = ssh_bind_new();
		
	BOOL welcomeMessage = FALSE;
		
	ssh_bind_options_set( sshbind, SSH_BIND_OPTIONS_DSAKEY, ts->sshs_DSAKeyHome );
	ssh_bind_options_set( sshbind, SSH_BIND_OPTIONS_RSAKEY, ts->sshs_RSAKeyHome );
	//ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
	
	//DEBUG("IMPORT RSA KEY %s\n", ts->sshs_RSAKeyHome );
	
	ssh_bind_options_set( sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, SSH_SERVER_PORT );	
	//verbose
	ssh_bind_options_set( sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "2" );
	ssh_bind_options_set( sshbind, SSH_BIND_OPTIONS_BINDADDR, "127.0.0.1" );
		
	if( ts->sshs_RSAKeyHome ) free( ts->sshs_RSAKeyHome );
	if( ts->sshs_DSAKeyHome ) free( ts->sshs_DSAKeyHome );
	
	// TODO: ts->sshs_Quit sometimes can not be read!
	while( ts != NULL && !ts->sshs_Quit )
	{
		DEBUG("Server options set\n");
	
	#ifdef WITH_PCAP
		set_pcap(session);
	#endif
		
		DEBUG("Server before bind\n");
		if( ssh_bind_listen( sshbind )<0 )
		{
			ERROR("Error listening to socket: %s\n",ssh_get_error(sshbind) );
			break;
		}
		
		DEBUG("Server before accept\n");

		session=ssh_new();
		r = ssh_bind_accept( sshbind , session );
		if( r==SSH_ERROR )
		{
			ERROR("error accepting a connection : %s\n",ssh_get_error(sshbind));
			break;
		}
		
		ssh_callbacks_init( &cb );
		SSHSession *sess = calloc( 1, sizeof( SSHSession ) );
		sess->sshs_Session = session;
		cb.userdata = sess;
		
		DEBUG("User data set\n");
		ssh_set_server_callbacks( session, &cb );
    
		if ( ssh_handle_key_exchange( session ) ) 
		{
			ERROR("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
			continue;
			//goto disconnect;
		}
	
		DEBUG("Connection accepted\n");
	
		ssh_set_auth_methods( session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC );
		
		//
		// New session/connection put it into thread
		//
		
		switch( fork() ) 
		{
			case 0:
				// Remove the SIGCHLD handler inherited from parent 
				signal(SIGCHLD, SIG_DFL);
			
				mainloop = ssh_event_new();
				ssh_event_add_session( mainloop, session );
			
				while( !(sess->sshs_Authenticated && sess->sshs_Chan != NULL) )
				{
					if( sess->sshs_Error )
					{
						ERROR("SSHSession error %d\n", sess->sshs_Error );
						break;
					}
			
					r = ssh_event_dopoll( mainloop, -1 );
					if( r == SSH_ERROR )
					{
						ERROR("Error : %s\n",ssh_get_error( session ) );
						ssh_disconnect( session );
						return 1;
					}
				
					strcpy( buf,	"------------------------------------------------------\n\r" \
									"--- Welcome in FC server, use help to work with me ---\n\r" \
									"------------------------------------------------------\n\r" );
				
					ssh_channel_write( sess->sshs_Chan, buf, strlen( buf ) );
				
					if( sess->sshs_Path == NULL )
					{
						sess->sshs_Path = calloc( 1024, sizeof(char) );
						sess->sshs_DispText = calloc( 1024+48, sizeof(char) );
					}
					strcpy( sess->sshs_Path, "/" );
		
					if( sess->sshs_Usr )
					{
						sprintf( sess->sshs_DispText, "%s:%s ", sess->sshs_Usr->u_Name, sess->sshs_Path );
					}else{
						sprintf( sess->sshs_DispText, ":%s ", sess->sshs_Path );
					}
				
					int i = 0;
				
					do
					{
						ssh_channel_write( sess->sshs_Chan, sess->sshs_DispText, strlen( sess->sshs_DispText ) );
					
						i = ssh_channel_read( sess->sshs_Chan, buf, 2048, 0 );
						if( i > 0 )
						{
							DEBUG("READING FROM CHANNEL %d - size %d  %d  %c -n  %d\n", i, strlen( buf ), buf[0], buf[0], '\n' );
							//ssh_channel_write( sess->sshs_Chan, buf, 1 );
						
							handleSSHCommands( sess, buf, i );
						}
					
						if( sess->sshs_Quit )
						{
							break;
						}
					
					}
					while( i>0 );
				
					if( sess->sshs_Quit )
						break;
				}
				DEBUG("Closing ssh connection\n");
			
				ssh_event_free( mainloop );
				ssh_disconnect( session );
				ssh_free( session );
			
				if( sess->sshs_DispText )
				{
					FFree( sess->sshs_DispText );
				}
			
				if( sess->sshs_Path )
				{
					FFree( sess->sshs_Path );
				}
			
				DEBUG("Connection released\n");

				FFree( sess );
			
				abort();
			
				DEBUG("AUTH\n");
				break;
			case -1:
				ERROR("Cannot create fork!\n");
				break;
		}
		

	#ifdef WITH_PCAP
		cleanup_pcap();
	#endif
		
	}	// main loop
	disconnect:
	DEBUG("DISCONNECTED\n");
#endif // ENABLE_SSH	
    return 0;
}