示例#1
0
/*
 * 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);
}
示例#2
0
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;
}