/* * Forks a ssh to the host listed in rc->hostname * Returns negative on error, with an errmsg in rc->errmsg. */ static int runssh( struct tcp_conn * rc, const char * amandad_path, const char * client_username, const char * ssh_keys, const char * client_port) { int rpipe[2], wpipe[2]; char *xamandad_path = (char *)amandad_path; char *xclient_username = (char *)client_username; char *xssh_keys = (char *)ssh_keys; char *xclient_port = (char *)client_port; GPtrArray *myargs; gchar *ssh_options[100] = {SSH_OPTIONS, NULL}; gchar **ssh_option; gchar *cmd; memset(rpipe, -1, sizeof(rpipe)); memset(wpipe, -1, sizeof(wpipe)); if (pipe(rpipe) < 0 || pipe(wpipe) < 0) { g_free(rc->errmsg); rc->errmsg = g_strdup_printf(_("pipe: %s"), strerror(errno)); return (-1); } if(!xamandad_path || strlen(xamandad_path) <= 1) xamandad_path = g_strjoin(NULL, amlibexecdir, "/", "amandad", NULL); if(!xclient_username || strlen(xclient_username) <= 1) xclient_username = CLIENT_LOGIN; if(!xclient_port || strlen(xclient_port) <= 1) xclient_port = NULL; myargs = g_ptr_array_sized_new(20); g_ptr_array_add(myargs, SSH); for (ssh_option = ssh_options; *ssh_option != NULL; ssh_option++) { g_ptr_array_add(myargs, *ssh_option); } g_ptr_array_add(myargs, "-l"); g_ptr_array_add(myargs, xclient_username); if (xclient_port) { g_ptr_array_add(myargs, "-p"); g_ptr_array_add(myargs, xclient_port); } if (ssh_keys && strlen(ssh_keys) > 1) { g_ptr_array_add(myargs, "-i"); g_ptr_array_add(myargs, xssh_keys); } g_ptr_array_add(myargs, rc->hostname); g_ptr_array_add(myargs, xamandad_path); g_ptr_array_add(myargs, "-auth=ssh"); g_ptr_array_add(myargs, NULL); cmd = g_strjoinv(" ", (gchar **)myargs->pdata); g_debug("exec: %s", cmd); g_free(cmd); switch (rc->pid = fork()) { case -1: g_free(rc->errmsg); rc->errmsg = g_strdup_printf(_("fork: %s"), strerror(errno)); aclose(rpipe[0]); aclose(rpipe[1]); aclose(wpipe[0]); aclose(wpipe[1]); return (-1); case 0: dup2(wpipe[0], 0); dup2(rpipe[1], 1); break; default: rc->read = rpipe[0]; aclose(rpipe[1]); rc->write = wpipe[1]; aclose(wpipe[0]); rc->child_watch = new_child_watch_source(rc->pid); g_source_set_callback(rc->child_watch, (GSourceFunc)ssh_child_watch_callback, rc, NULL); g_source_attach(rc->child_watch, NULL); g_source_unref(rc->child_watch); return (0); } /* drop root privs for good */ set_root_privs(-1); safe_fd(-1, 0); execvp(SSH, (gchar **)myargs->pdata); error("error: couldn't exec %s: %s", SSH, strerror(errno)); /* should never go here, shut up compiler warning */ return(-1); }
static gboolean start_impl( XferElement *elt) { char *tmpbuf; XferFilterProcess *self = (XferFilterProcess *)elt; char *cmd_str; char **argv; char *errmsg; char **env; int rfd, wfd; /* first build up a log message of what we're going to do, properly shell quoted */ argv = self->argv; cmd_str = g_shell_quote(*(argv++)); while (*argv) { char *qarg = g_shell_quote(*(argv++)); tmpbuf = g_strconcat(cmd_str, " ", qarg, NULL); g_free(cmd_str); cmd_str = tmpbuf; g_free(qarg); } g_debug("%s spawning: %s", xfer_element_repr(elt), cmd_str); rfd = xfer_element_swap_output_fd(elt->upstream, -1); wfd = xfer_element_swap_input_fd(elt->downstream, -1); /* now fork off the child and connect the pipes */ switch (self->child_pid = fork()) { case -1: error("cannot fork: %s", strerror(errno)); /* NOTREACHED */ case 0: /* child */ /* first, copy our fd's out of the stdio range */ while (rfd >= 0 && rfd <= STDERR_FILENO) rfd = dup(rfd); while (wfd >= 0 && wfd <= STDERR_FILENO) wfd = dup(wfd); /* set up stdin, stdout, and stderr, overwriting anything already open * on those fd's */ if (rfd > 0) dup2(rfd, STDIN_FILENO); if (wfd > 0) dup2(wfd, STDOUT_FILENO); dup2(self->pipe_err[1], STDERR_FILENO); /* and close everything else */ safe_fd(-1, 0); env = safe_env(); if (self->need_root && !become_root()) { errmsg = g_strdup_printf("could not become root: %s\n", strerror(errno)); full_write(STDERR_FILENO, errmsg, strlen(errmsg)); exit(1); } execve(self->argv[0], self->argv, env); free_env(env); errmsg = g_strdup_printf("exec of '%s' failed: %s\n", self->argv[0], strerror(errno)); full_write(STDERR_FILENO, errmsg, strlen(errmsg)); exit(1); default: /* parent */ break; } g_free(cmd_str); /* close the pipe fd's */ close(rfd); close(wfd); close(self->pipe_err[1]); /* watch for child death */ self->child_watch = new_child_watch_source(self->child_pid); g_source_set_callback(self->child_watch, (GSourceFunc)child_watch_callback, self, NULL); g_source_attach(self->child_watch, NULL); g_source_unref(self->child_watch); return TRUE; }