Ejemplo n.º 1
0
/* hdr parameter is received from dom0, so it is trusted */
void handle_server_exec_request(struct msg_header *hdr)
{
    struct exec_params params;
    int buf_len = hdr->len-sizeof(params);
    char buf[buf_len];
    pid_t child_agent;
    int client_fd;

    assert(hdr->len >= sizeof(params));

    if (libvchan_recv(ctrl_vchan, &params, sizeof(params)) < 0)
        handle_vchan_error("read exec params");
    if (libvchan_recv(ctrl_vchan, buf, buf_len) < 0)
        handle_vchan_error("read exec cmd");

    if ((hdr->type == MSG_EXEC_CMDLINE || hdr->type == MSG_JUST_EXEC) &&
            !strstr(buf, ":nogui:")) {
        int child_socket = try_fork_server(hdr->type,
                params.connect_domain, params.connect_port,
                buf, buf_len);
        if (child_socket >= 0) {
            register_vchan_connection(-1, child_socket,
                    params.connect_domain, params.connect_port);
            return;
        }
    }
    if (hdr->type == MSG_SERVICE_CONNECT && sscanf(buf, "SOCKET%d", &client_fd)) {
        /* FIXME: Maybe add some check if client_fd is really FD to some
         * qrexec-client-vm process; but this data comes from qrexec-daemon
         * (which sends back what it got from us earlier), so it isn't critical.
         */
        if (write(client_fd, &params, sizeof(params)) < 0) {
            /* ignore */
        }
        /* No need to send request_id (buf) - the client don't need it, there
         * is only meaningless (for the client) socket FD */
        /* Register connection even if there was an error sending params to
         * qrexec-client-vm. This way the mainloop will clean the things up
         * (close socket, send MSG_CONNECTION_TERMINATED) when qrexec-client-vm
         * will close the socket (terminate itself). */
        register_vchan_connection(-1, client_fd,
                params.connect_domain, params.connect_port);
        return;
    }

    /* No fork server case */
    child_agent = handle_new_process(hdr->type,
            params.connect_domain, params.connect_port,
            buf, buf_len);

    register_vchan_connection(child_agent, -1,
            params.connect_domain, params.connect_port);
}
Ejemplo n.º 2
0
void handle_server_cmd()
{
    struct msg_header s_hdr;

    if (libvchan_recv(ctrl_vchan, &s_hdr, sizeof(s_hdr)) < 0)
        handle_vchan_error("read s_hdr");

    //      fprintf(stderr, "got %x %x %x\n", s_hdr.type, s_hdr.client_id,
    //              s_hdr.len);

    switch (s_hdr.type) {
        case MSG_EXEC_CMDLINE:
        case MSG_JUST_EXEC:
        case MSG_SERVICE_CONNECT:
            wake_meminfo_writer();
            handle_server_exec_request(&s_hdr);
            break;
        case MSG_SERVICE_REFUSED:
            handle_service_refused(&s_hdr);
            break;
        default:
            fprintf(stderr, "msg type from daemon is %d ?\n",
                    s_hdr.type);
            exit(1);
    }
}
Ejemplo n.º 3
0
static void rec_packet(libvchan_t * con) {
    char done = 1;
    int data[4];
		struct camera_data ca;

    libvchan_wait(con);
    int readSize = libvchan_recv(con, data, 4*sizeof(int));
    assert(readSize == 4*sizeof(int));
    DVM("received bounding box packet\n");

    //here are your corners Lee!
    ca.bbox_l = data[0];
    ca.bbox_r = data[1];
    ca.bbox_t = data[2];
    ca.bbox_b = data[3];

    /* int xmid = ((r + l) / 2) - 160; */
    /* int ymid = ((b + t) / 2) - 100; */

    /* ymid = -1.0*ymid; //sign change (based on how the camera is oriented) */

    /* //here are your angles Lee! */
    /* ca.angle_x = ((float) xmid)*(0.00410666); */
    /* ca.angle_y = ((float) ymid)*(0.00410666); */

    if (camera_vm_Output_from_vm_0_write_camera_data(&ca)) {
	DVM("wrote bounding box\n");
    } else {
	DVM("failed to write bouding box\n");
    }

    DVM("camera_vm: sending ack\n");
    libvchan_send(con, &done, sizeof(char));
}
Ejemplo n.º 4
0
int handle_agent_hello(libvchan_t *ctrl, const char *domain_name)
{
    struct msg_header hdr;
    struct peer_info info;

    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);
        incompatible_protocol_error_message(domain_name, info.version);
        return -1;
    }

    /* send own HELLO */
    /* those messages are the same as received from agent, but set it again for
     * readability */
    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;
    }

    return 0;
}
Ejemplo n.º 5
0
static void handle_execute_service(void)
{
    int i;
    int policy_pending_slot;
    pid_t pid;
    struct trigger_service_params untrusted_params, params;
    char remote_domain_id_str[10];

    if (libvchan_recv(vchan, &untrusted_params, sizeof(untrusted_params)) < 0)
        handle_vchan_error("recv params");

    /* sanitize start */
    ENSURE_NULL_TERMINATED(untrusted_params.service_name);
    ENSURE_NULL_TERMINATED(untrusted_params.target_domain);
    ENSURE_NULL_TERMINATED(untrusted_params.request_id.ident);
    sanitize_name(untrusted_params.service_name, "+");
    sanitize_name(untrusted_params.target_domain, "@:");
    sanitize_name(untrusted_params.request_id.ident, " ");
    params = untrusted_params;
    /* sanitize end */

    policy_pending_slot = find_policy_pending_slot();
    if (policy_pending_slot < 0) {
        fprintf(stderr, "Service request denied, too many pending requests\n");
        send_service_refused(vchan, &untrusted_params.request_id);
        return;
    }

    switch (pid=fork()) {
        case -1:
            perror("fork");
            exit(1);
        case 0:
            break;
        default:
            policy_pending[policy_pending_slot].pid = pid;
            policy_pending[policy_pending_slot].params = untrusted_params.request_id;
            return;
    }
    for (i = 3; i < MAX_FDS; i++)
        close(i);
    signal(SIGCHLD, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
    snprintf(remote_domain_id_str, sizeof(remote_domain_id_str), "%d",
            remote_domain_id);
    execl("/usr/bin/qrexec-policy", "qrexec-policy", "--",
            remote_domain_id_str, remote_domain_name, params.target_domain,
            params.service_name, params.request_id.ident, NULL);
    perror("execl");
    _exit(1);
}
Ejemplo n.º 6
0
void handle_service_refused(struct msg_header *hdr)
{
    struct service_params params;
    int socket_fd;

    if (hdr->len != sizeof(params)) {
        fprintf(stderr, "Invalid msg 0x%x length (%d)\n", MSG_SERVICE_REFUSED, hdr->len);
        exit(1);
    }

    if (libvchan_recv(ctrl_vchan, &params, sizeof(params)) < 0)
        handle_vchan_error("read exec params");

    if (sscanf(params.ident, "SOCKET%d", &socket_fd))
        close(socket_fd);
    else
        fprintf(stderr, "Received REFUSED for unknown service request '%s'\n", params.ident);
}
Ejemplo n.º 7
0
static void handle_connection_terminated()
{
    struct exec_params untrusted_params, params;

    if (libvchan_recv(vchan, &untrusted_params, sizeof(untrusted_params)) < 0)
        handle_vchan_error("recv params");
    /* sanitize start */
    if (untrusted_params.connect_port < VCHAN_BASE_DATA_PORT ||
            untrusted_params.connect_port >= VCHAN_BASE_DATA_PORT+MAX_CLIENTS) {
        fprintf(stderr, "Invalid port in MSG_CONNECTION_TERMINATED (%d)\n",
                untrusted_params.connect_port);
        exit(1);
    }
    /* untrusted_params.connect_domain even if invalid will not harm - in worst
     * case the port will not be released */
    params = untrusted_params;
    /* sanitize end */
    release_vchan_port(params.connect_port, params.connect_domain);
}
Ejemplo n.º 8
0
static void handle_message_from_agent(void)
{
    struct msg_header hdr, untrusted_hdr;

    if (libvchan_recv(vchan, &untrusted_hdr, sizeof(untrusted_hdr)) < 0)
        handle_vchan_error("recv hdr");
    /* sanitize start */
    sanitize_message_from_agent(&untrusted_hdr);
    hdr = untrusted_hdr;
    /* sanitize end */

    //      fprintf(stderr, "got %x %x %x\n", hdr.type, hdr.client_id,
    //              hdr.len);

    switch (hdr.type) {
        case MSG_TRIGGER_SERVICE:
            handle_execute_service();
            return;
        case MSG_CONNECTION_TERMINATED:
            handle_connection_terminated();
            return;
    }
}
Ejemplo n.º 9
0
static int handle_vchan_data(libvchan_t *vchan, struct buffer *stdin_buf)
{
    int status;
    struct msg_header hdr;
    char buf[MAX_DATA_CHUNK];

    if (local_stdin_fd != -1) {
        switch(flush_client_data(local_stdin_fd, stdin_buf)) {
            case WRITE_STDIN_ERROR:
                perror("write stdin");
                close(local_stdin_fd);
                local_stdin_fd = -1;
                break;
            case WRITE_STDIN_BUFFERED:
                return WRITE_STDIN_BUFFERED;
            case WRITE_STDIN_OK:
                break;
        }
    }
    if (libvchan_recv(vchan, &hdr, sizeof hdr) < 0) {
        perror("read vchan");
        do_exit(1);
    }
    if (hdr.len > MAX_DATA_CHUNK) {
        fprintf(stderr, "client_header.len=%d\n", hdr.len);
        do_exit(1);
    }
    if (!read_vchan_all(vchan, buf, hdr.len)) {
        perror("read daemon");
        do_exit(1);
    }

    switch (hdr.type) {
        /* both directions because we can serve as either end of service call */
        case MSG_DATA_STDIN:
        case MSG_DATA_STDOUT:
            if (local_stdin_fd == -1)
                break;
            if (replace_esc_stdout)
                do_replace_esc(buf, hdr.len);
            if (hdr.len == 0) {
                /* restore flags, as we may have not the only copy of this file descriptor
                */
                if (local_stdin_fd != -1)
                    set_block(local_stdin_fd);
                close(local_stdin_fd);
                local_stdin_fd = -1;
            } else {
                switch (write_stdin(local_stdin_fd, buf, hdr.len, stdin_buf)) {
                    case WRITE_STDIN_BUFFERED:
                        return WRITE_STDIN_BUFFERED;
                    case WRITE_STDIN_ERROR:
                        if (errno == EPIPE) {
                            // local process have closed its stdin, handle data in oposite
                            // direction (if any) before exit
                            close(local_stdin_fd);
                            local_stdin_fd = -1;
                        } else {
                            perror("write local stdout");
                            do_exit(1);
                        }
                        break;
                    case WRITE_STDIN_OK:
                        break;
                }
            }
            break;
        case MSG_DATA_STDERR:
            if (replace_esc_stderr)
                do_replace_esc(buf, hdr.len);
            write_all(2, buf, hdr.len);
            break;
        case MSG_DATA_EXIT_CODE:
            libvchan_close(vchan);
            if (hdr.len < sizeof(status))
                status = 255;
            else
                memcpy(&status, buf, sizeof(status));

            flush_client_data(local_stdin_fd, stdin_buf);
            do_exit(status);
            break;
        default:
            fprintf(stderr, "unknown msg %d\n", hdr.type);
            do_exit(1);
    }
    /* intentionally do not distinguish between _ERROR and _OK, because in case
     * of write error, we simply eat the data - no way to report it to the
     * other side */
    return WRITE_STDIN_OK;
}