diff --git a/qrexec/qrexec-agent-data.c b/qrexec/qrexec-agent-data.c index 0f41222..1378e29 100644 --- a/qrexec/qrexec-agent-data.c +++ b/qrexec/qrexec-agent-data.c @@ -45,8 +45,8 @@ pid_t child_process_pid; static void sigchld_handler(int __attribute__((__unused__))x) { - child_exited = 1; - signal(SIGCHLD, sigchld_handler); + child_exited = 1; + signal(SIGCHLD, sigchld_handler); } static void sigusr1_handler(int __attribute__((__unused__))x) @@ -55,43 +55,55 @@ static void sigusr1_handler(int __attribute__((__unused__))x) signal(SIGUSR1, SIG_IGN); } - -void no_colon_in_cmd() +int handle_handshake(libvchan_t *ctrl) { - fprintf(stderr, - "cmdline is supposed to be in user:command form\n"); - exit(1); + struct msg_header hdr; + struct peer_info info; + + /* send own HELLO */ + hdr.type = MSG_HELLO; + hdr.len = sizeof(info); + info.version = QREXEC_PROTOCOL_VERSION; + + if (libvchan_send(ctrl, &hdr, sizeof(hdr)) != sizeof(hdr)) { + fprintf(stderr, "Failed to send HELLO hdr to agent\n"); + return -1; + } + + if (libvchan_send(ctrl, &info, sizeof(info)) != sizeof(info)) { + fprintf(stderr, "Failed to send HELLO hdr to agent\n"); + return -1; + } + + /* receive MSG_HELLO from remote */ + if (libvchan_recv(ctrl, &hdr, sizeof(hdr)) != sizeof(hdr)) { + fprintf(stderr, "Failed to read agent HELLO hdr\n"); + return -1; + } + + if (hdr.type != MSG_HELLO || hdr.len != sizeof(info)) { + fprintf(stderr, "Invalid HELLO packet received: type %d, len %d\n", hdr.type, hdr.len); + return -1; + } + + if (libvchan_recv(ctrl, &info, sizeof(info)) != sizeof(info)) { + fprintf(stderr, "Failed to read agent HELLO body\n"); + return -1; + } + + if (info.version != QREXEC_PROTOCOL_VERSION) { + fprintf(stderr, "Incompatible agent protocol version (remote %d, local %d)\n", info.version, QREXEC_PROTOCOL_VERSION); + return -1; + } + + + return 0; } -void do_exec(char *cmd) -{ - char buf[strlen(QUBES_RPC_MULTIPLEXER_PATH) + strlen(cmd) - strlen(RPC_REQUEST_COMMAND) + 1]; - char *realcmd = index(cmd, ':'); - if (!realcmd) - no_colon_in_cmd(); - /* mark end of username and move to command */ - *realcmd = 0; - realcmd++; - /* ignore "nogui:" prefix in linux agent */ - if (strncmp(realcmd, "nogui:", 6) == 0) - realcmd+=6; - /* replace magic RPC cmd with RPC multiplexer path */ - if (strncmp(realcmd, RPC_REQUEST_COMMAND " ", strlen(RPC_REQUEST_COMMAND)+1)==0) { - strcpy(buf, QUBES_RPC_MULTIPLEXER_PATH); - strcpy(buf + strlen(QUBES_RPC_MULTIPLEXER_PATH), realcmd + strlen(RPC_REQUEST_COMMAND)); - realcmd = buf; - } - signal(SIGCHLD, SIG_DFL); - signal(SIGPIPE, SIG_DFL); - - execl("/bin/su", "su", "-", cmd, "-c", realcmd, NULL); - perror("execl"); - exit(1); -} int handle_just_exec(char *cmdline) { - int fdn, pid; + int fdn, pid; switch (pid = fork()) { case -1: @@ -105,20 +117,20 @@ int handle_just_exec(char *cmdline) exit(1); default:; } - fprintf(stderr, "executed (nowait) %s pid %d\n", cmdline, pid); + fprintf(stderr, "executed (nowait) %s pid %d\n", cmdline, pid); return 0; } void send_exit_code(libvchan_t *data_vchan, int status) { - struct msg_header hdr; - hdr.type = MSG_DATA_EXIT_CODE; - hdr.len = sizeof(status); - if (libvchan_send(data_vchan, &hdr, sizeof(hdr)) < 0) - handle_vchan_error("write hdr"); - if (libvchan_send(data_vchan, &status, sizeof(status)) < 0) - handle_vchan_error("write status"); - fprintf(stderr, "send exit code %d\n", status); + struct msg_header hdr; + hdr.type = MSG_DATA_EXIT_CODE; + hdr.len = sizeof(status); + if (libvchan_send(data_vchan, &hdr, sizeof(hdr)) < 0) + handle_vchan_error("write hdr"); + if (libvchan_send(data_vchan, &status, sizeof(status)) < 0) + handle_vchan_error("write status"); + fprintf(stderr, "send exit code %d\n", status); } /* handle data from specified FD and send over vchan link diff --git a/qrexec/qrexec-agent.c b/qrexec/qrexec-agent.c index f00e133..f6a96b9 100644 --- a/qrexec/qrexec-agent.c +++ b/qrexec/qrexec-agent.c @@ -55,7 +55,38 @@ int passfd_socket; int meminfo_write_started = 0; -void do_exec(const char *cmd); +void no_colon_in_cmd() +{ + fprintf(stderr, + "cmdline is supposed to be in user:command form\n"); + exit(1); +} + +void do_exec(const char *cmd) +{ + char buf[strlen(QUBES_RPC_MULTIPLEXER_PATH) + strlen(cmd) - strlen(RPC_REQUEST_COMMAND) + 1]; + char *realcmd = index(cmd, ':'); + if (!realcmd) + no_colon_in_cmd(); + /* mark end of username and move to command */ + *realcmd = 0; + realcmd++; + /* ignore "nogui:" prefix in linux agent */ + if (strncmp(realcmd, "nogui:", 6) == 0) + realcmd+=6; + /* replace magic RPC cmd with RPC multiplexer path */ + if (strncmp(realcmd, RPC_REQUEST_COMMAND " ", strlen(RPC_REQUEST_COMMAND)+1)==0) { + strcpy(buf, QUBES_RPC_MULTIPLEXER_PATH); + strcpy(buf + strlen(QUBES_RPC_MULTIPLEXER_PATH), realcmd + strlen(RPC_REQUEST_COMMAND)); + realcmd = buf; + } + signal(SIGCHLD, SIG_DFL); + signal(SIGPIPE, SIG_DFL); + + execl("/bin/su", "su", "-", cmd, "-c", realcmd, NULL); + perror("execl"); + exit(1); +} void handle_vchan_error(const char *op) { @@ -63,51 +94,6 @@ void handle_vchan_error(const char *op) exit(1); } -int handle_handshake(libvchan_t *ctrl) -{ - struct msg_header hdr; - struct peer_info info; - - /* send own HELLO */ - hdr.type = MSG_HELLO; - hdr.len = sizeof(info); - info.version = QREXEC_PROTOCOL_VERSION; - - if (libvchan_send(ctrl, &hdr, sizeof(hdr)) != sizeof(hdr)) { - fprintf(stderr, "Failed to send HELLO hdr to agent\n"); - return -1; - } - - if (libvchan_send(ctrl, &info, sizeof(info)) != sizeof(info)) { - fprintf(stderr, "Failed to send HELLO hdr to agent\n"); - return -1; - } - - /* receive MSG_HELLO from remote */ - if (libvchan_recv(ctrl, &hdr, sizeof(hdr)) != sizeof(hdr)) { - fprintf(stderr, "Failed to read agent HELLO hdr\n"); - return -1; - } - - if (hdr.type != MSG_HELLO || hdr.len != sizeof(info)) { - fprintf(stderr, "Invalid HELLO packet received: type %d, len %d\n", hdr.type, hdr.len); - return -1; - } - - if (libvchan_recv(ctrl, &info, sizeof(info)) != sizeof(info)) { - fprintf(stderr, "Failed to read agent HELLO body\n"); - return -1; - } - - if (info.version != QREXEC_PROTOCOL_VERSION) { - fprintf(stderr, "Incompatible agent protocol version (remote %d, local %d)\n", info.version, QREXEC_PROTOCOL_VERSION); - return -1; - } - - - return 0; -} - void init() { /* FIXME: This 0 is remote domain ID */ @@ -262,27 +248,31 @@ int find_connection(int pid) return -1; } +void release_connection(int id) { + struct msg_header hdr; + struct exec_params params; + + hdr.type = MSG_CONNECTION_TERMINATED; + hdr.len = sizeof(struct exec_params); + params.connect_domain = connection_info[id].connect_domain; + params.connect_port = connection_info[id].connect_port; + if (libvchan_send(ctrl_vchan, &hdr, sizeof(hdr)) < 0) + handle_vchan_error("send"); + if (libvchan_send(ctrl_vchan, ¶ms, sizeof(params)) < 0) + handle_vchan_error("send"); + connection_info[id].pid = 0; +} void reap_children() { int status; int pid; int id; - struct msg_header hdr; - struct exec_params params; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { id = find_connection(pid); if (id < 0) continue; - hdr.type = MSG_CONNECTION_TERMINATED; - hdr.len = sizeof(struct exec_params); - params.connect_domain = connection_info[id].connect_domain; - params.connect_port = connection_info[id].connect_port; - if (libvchan_send(ctrl_vchan, &hdr, sizeof(hdr)) < 0) - handle_vchan_error("send"); - if (libvchan_send(ctrl_vchan, ¶ms, sizeof(params)) < 0) - handle_vchan_error("send"); - connection_info[id].pid = 0; + release_connection(id); } child_exited = 0; } diff --git a/qrexec/qrexec-agent.h b/qrexec/qrexec-agent.h index 38c554b..ebf7e8d 100644 --- a/qrexec/qrexec-agent.h +++ b/qrexec/qrexec-agent.h @@ -21,6 +21,7 @@ int handle_handshake(libvchan_t *ctrl); void handle_vchan_error(const char *op); +void do_exec(const char *cmd); pid_t handle_new_process(int type, int connect_domain, int connect_port,