Ejemplo n.º 1
0
mexp_h *
mexp_spawnlf (unsigned flags, const char *file, const char *arg, ...)
{
  char **argv, **new_argv;
  size_t i;
  va_list args;
  mexp_h *h;

  argv = malloc (sizeof (char *));
  if (argv == NULL)
    return NULL;
  argv[0] = (char *) arg;

  va_start (args, arg);
  for (i = 1; arg != NULL; ++i) {
    arg = va_arg (args, const char *);
    new_argv = realloc (argv, sizeof (char *) * (i+1));
    if (new_argv == NULL) {
      free (argv);
      va_end (args);
      return NULL;
    }
    argv = new_argv;
    argv[i] = (char *) arg;
  }

  h = mexp_spawnvf (flags, file, argv);
  free (argv);
  va_end (args);
  return h;
}
Ejemplo n.º 2
0
/**
 * Start ssh subprocess with the standard arguments and possibly some
 * optional arguments.  Also handles authentication.
 */
static mexp_h *
start_ssh (unsigned spawn_flags, struct config *config,
           char **extra_args, int wait_prompt)
{
  size_t i, j, nr_args, count;
  char port_str[64];
  char connect_timeout_str[128];
  CLEANUP_FREE /* [sic] */ const char **args = NULL;
  mexp_h *h;
  const int ovecsize = 12;
  int ovector[ovecsize];
  int saved_timeout;
  int using_password_auth;

  if (cache_ssh_identity (config) == -1)
    return NULL;

  /* Are we using password or identity authentication? */
  using_password_auth = config->identity_file == NULL;

  /* Create the ssh argument array. */
  nr_args = 0;
  if (extra_args != NULL)
    nr_args = guestfs_int_count_strings (extra_args);

  if (using_password_auth)
    nr_args += 13;
  else
    nr_args += 15;
  args = malloc (sizeof (char *) * nr_args);
  if (args == NULL)
    error (EXIT_FAILURE, errno, "malloc");

  j = 0;
  args[j++] = "ssh";
  args[j++] = "-p";             /* Port. */
  snprintf (port_str, sizeof port_str, "%d", config->port);
  args[j++] = port_str;
  args[j++] = "-l";             /* Username. */
  args[j++] = config->username ? config->username : "******";
  args[j++] = "-o";             /* Host key will always be novel. */
  args[j++] = "StrictHostKeyChecking=no";
  args[j++] = "-o";             /* ConnectTimeout */
  snprintf (connect_timeout_str, sizeof connect_timeout_str,
            "ConnectTimeout=%d", SSH_TIMEOUT);
  args[j++] = connect_timeout_str;
  if (using_password_auth) {
    /* Only use password authentication. */
    args[j++] = "-o";
    args[j++] = "PreferredAuthentications=keyboard-interactive,password";
  }
  else {
    /* Use identity file (private key). */
    args[j++] = "-o";
    args[j++] = "PreferredAuthentications=publickey";
    args[j++] = "-i";
    args[j++] = config->identity_file;
  }
  if (extra_args != NULL) {
    for (i = 0; extra_args[i] != NULL; ++i)
      args[j++] = extra_args[i];
  }
  args[j++] = config->server;   /* Conversion server. */
  args[j++] = NULL;
  assert (j == nr_args);

#if DEBUG_STDERR
  fputs ("ssh command: ", stderr);
  for (i = 0; i < nr_args - 1; ++i) {
    if (i > 0) fputc (' ', stderr);
    fputs (args[i], stderr);
  }
  fputc ('\n', stderr);
#endif

  /* Create the miniexpect handle. */
  h = mexp_spawnvf (spawn_flags, "ssh", (char **) args);
  if (h == NULL) {
    set_ssh_internal_error ("ssh: mexp_spawnvf: %m");
    return NULL;
  }

  /* We want the ssh ConnectTimeout to be less than the miniexpect
   * timeout, so that if the server is completely unresponsive we
   * still see the error from ssh, not a timeout from miniexpect.  The
   * obvious solution to this is to set ConnectTimeout (above) and to
   * set the miniexpect timeout to be a little bit larger.
   */
  mexp_set_timeout (h, SSH_TIMEOUT + 20);

  if (using_password_auth &&
      config->password && strlen (config->password) > 0) {
    CLEANUP_FREE char *ssh_message = NULL;

    /* Wait for the password prompt. */
  wait_password_again:
    switch (mexp_expect (h,
                         (mexp_regexp[]) {
                           { 100, .re = password_re },