Esempio n. 1
0
int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
        Machine *m = userdata;
        int r;

        assert(message);
        assert(m);

        r = bus_verify_polkit_async(
                        message,
                        CAP_KILL,
                        "org.freedesktop.machine1.manage-machines",
                        NULL,
                        false,
                        UID_INVALID,
                        &m->manager->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* Will call us back */

        r = machine_stop(m);
        if (r < 0)
                return r;

        return sd_bus_reply_method_return(message, NULL);
}
Esempio n. 2
0
int bus_image_method_remove(
                sd_bus_message *message,
                void *userdata,
                sd_bus_error *error) {

        Image *image = userdata;
        Manager *m = image->userdata;
        int r;

        assert(message);
        assert(image);

        r = bus_verify_polkit_async(
                        message,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.machine1.manage-images",
                        false,
                        UID_INVALID,
                        &m->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* Will call us back */

        r = image_remove(image);
        if (r < 0)
                return r;

        return sd_bus_reply_method_return(message, NULL);
}
Esempio n. 3
0
static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error *error) {
    Context *c = userdata;
    const char *name;
    int interactive;
    char *h;
    int r;

    assert(m);
    assert(c);

    r = sd_bus_message_read(m, "sb", &name, &interactive);
    if (r < 0)
        return r;

    if (isempty(name))
        name = c->data[PROP_STATIC_HOSTNAME];

    if (isempty(name))
        name = "localhost";

    if (!hostname_is_valid(name, false))
        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);

    if (streq_ptr(name, c->data[PROP_HOSTNAME]))
        return sd_bus_reply_method_return(m, NULL);

    r = bus_verify_polkit_async(
            m,
            CAP_SYS_ADMIN,
            "org.freedesktop.hostname1.set-hostname",
            NULL,
            interactive,
            UID_INVALID,
            &c->polkit_registry,
            error);
    if (r < 0)
        return r;
    if (r == 0)
        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */

    h = strdup(name);
    if (!h)
        return -ENOMEM;

    free(c->data[PROP_HOSTNAME]);
    c->data[PROP_HOSTNAME] = h;

    r = context_update_kernel_hostname(c);
    if (r < 0) {
        log_error_errno(r, "Failed to set host name: %m");
        return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r));
    }

    log_info("Changed host name to '%s'", strna(c->data[PROP_HOSTNAME]));

    (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "Hostname", NULL);

    return sd_bus_reply_method_return(m, NULL);
}
Esempio n. 4
0
static int bus_image_method_detach(
                sd_bus_message *message,
                void *userdata,
                sd_bus_error *error) {

        PortableChange *changes = NULL;
        Image *image = userdata;
        Manager *m = image->userdata;
        size_t n_changes = 0;
        int r, runtime;

        assert(message);
        assert(image);
        assert(m);

        r = sd_bus_message_read(message, "b", &runtime);
        if (r < 0)
                return r;

        r = bus_verify_polkit_async(
                        message,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.portable1.attach-images",
                        NULL,
                        false,
                        UID_INVALID,
                        &m->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* Will call us back */

        r = portable_detach(
                        sd_bus_message_get_bus(message),
                        image->path,
                        runtime ? PORTABLE_RUNTIME : 0,
                        &changes,
                        &n_changes,
                        error);
        if (r < 0)
                goto finish;

        r = reply_portable_changes(message, changes, n_changes);

finish:
        portable_changes_free(changes, n_changes);
        return r;
}
Esempio n. 5
0
int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
        Machine *m = userdata;
        const char *swho;
        int32_t signo;
        KillWho who;
        int r;

        assert(message);
        assert(m);

        r = sd_bus_message_read(message, "si", &swho, &signo);
        if (r < 0)
                return r;

        if (isempty(swho))
                who = KILL_ALL;
        else {
                who = kill_who_from_string(swho);
                if (who < 0)
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
        }

        if (signo <= 0 || signo >= _NSIG)
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);

        r = bus_verify_polkit_async(
                        message,
                        CAP_KILL,
                        "org.freedesktop.machine1.manage-machines",
                        NULL,
                        false,
                        UID_INVALID,
                        &m->manager->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* Will call us back */

        r = machine_kill(m, who, signo);
        if (r < 0)
                return r;

        return sd_bus_reply_method_return(message, NULL);
}
Esempio n. 6
0
int bus_image_method_rename(
                sd_bus_message *message,
                void *userdata,
                sd_bus_error *error) {

        Image *image = userdata;
        Manager *m = image->userdata;
        const char *new_name;
        int r;

        assert(message);
        assert(image);

        r = sd_bus_message_read(message, "s", &new_name);
        if (r < 0)
                return r;

        if (!image_name_is_valid(new_name))
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", new_name);

        r = bus_verify_polkit_async(
                        message,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.machine1.manage-images",
                        NULL,
                        false,
                        UID_INVALID,
                        &m->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* Will call us back */

        r = image_rename(image, new_name);
        if (r < 0)
                return r;

        return sd_bus_reply_method_return(message, NULL);
}
Esempio n. 7
0
static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        Context *c = userdata;
        int interactive, r;

        assert(m);
        assert(c);

        if (!c->has_uuid)
                return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID, "Failed to read product UUID from /sys/class/dmi/id/product_uuid");

        r = sd_bus_message_read(m, "b", &interactive);
        if (r < 0)
                return r;

        r = bus_verify_polkit_async(
                        m,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.hostname1.get-product-uuid",
                        NULL,
                        interactive,
                        UID_INVALID,
                        &c->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */

        r = sd_bus_message_new_method_return(m, &reply);
        if (r < 0)
                return r;

        r = sd_bus_message_append_array(reply, 'y', &c->uuid, sizeof(c->uuid));
        if (r < 0)
                return r;

        return sd_bus_send(NULL, reply, NULL);
}
Esempio n. 8
0
int bus_image_method_set_limit(
                sd_bus_message *message,
                void *userdata,
                sd_bus_error *error) {

        Image *image = userdata;
        Manager *m = image->userdata;
        uint64_t limit;
        int r;

        assert(message);

        r = sd_bus_message_read(message, "t", &limit);
        if (r < 0)
                return r;
        if (!FILE_SIZE_VALID_OR_INFINITY(limit))
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "New limit out of range");

        r = bus_verify_polkit_async(
                        message,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.machine1.manage-images",
                        NULL,
                        false,
                        UID_INVALID,
                        &m->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* Will call us back */

        r = image_set_limit(image, limit);
        if (r < 0)
                return r;

        return sd_bus_reply_method_return(message, NULL);
}
Esempio n. 9
0
static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) {
    int interactive;
    const char *name;
    int r;

    assert(c);
    assert(m);

    r = sd_bus_message_read(m, "sb", &name, &interactive);
    if (r < 0)
        return r;

    if (isempty(name))
        name = NULL;

    if (streq_ptr(name, c->data[prop]))
        return sd_bus_reply_method_return(m, NULL);

    /* Since the pretty hostname should always be changed at the
     * same time as the static one, use the same policy action for
     * both... */

    r = bus_verify_polkit_async(
            m,
            CAP_SYS_ADMIN,
            prop == PROP_PRETTY_HOSTNAME ? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
            NULL,
            interactive,
            UID_INVALID,
            &c->polkit_registry,
            error);
    if (r < 0)
        return r;
    if (r == 0)
        return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */

    if (isempty(name)) {
        c->data[prop] = mfree(c->data[prop]);
    } else {
        char *h;

        /* The icon name might ultimately be used as file
         * name, so better be safe than sorry */

        if (prop == PROP_ICON_NAME && !filename_is_valid(name))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
        if (prop == PROP_PRETTY_HOSTNAME && string_has_cc(name, NULL))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
        if (prop == PROP_CHASSIS && !valid_chassis(name))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
        if (prop == PROP_DEPLOYMENT && !valid_deployment(name))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid deployment '%s'", name);
        if (prop == PROP_LOCATION && string_has_cc(name, NULL))
            return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid location '%s'", name);

        h = strdup(name);
        if (!h)
            return -ENOMEM;

        free(c->data[prop]);
        c->data[prop] = h;
    }

    r = context_write_data_machine_info(c);
    if (r < 0) {
        log_error_errno(r, "Failed to write machine info: %m");
        return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %s", strerror(-r));
    }

    log_info("Changed %s to '%s'",
             prop == PROP_PRETTY_HOSTNAME ? "pretty host name" :
             prop == PROP_DEPLOYMENT ? "deployment" :
             prop == PROP_LOCATION ? "location" :
             prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop]));

    (void) sd_bus_emit_properties_changed(
        sd_bus_message_get_bus(m),
        "/org/freedesktop/hostname1",
        "org.freedesktop.hostname1",
        prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" :
        prop == PROP_DEPLOYMENT ? "Deployment" :
        prop == PROP_LOCATION ? "Location" :
        prop == PROP_CHASSIS ? "Chassis" : "IconName" , NULL);

    return sd_bus_reply_method_return(m, NULL);
}
Esempio n. 10
0
int bus_image_method_remove(
                sd_bus_message *message,
                void *userdata,
                sd_bus_error *error) {

        _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
        Image *image = userdata;
        Manager *m = image->userdata;
        pid_t child;
        int r;

        assert(message);
        assert(image);

        if (m->n_operations >= OPERATIONS_MAX)
                return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing operations.");

        r = bus_verify_polkit_async(
                        message,
                        CAP_SYS_ADMIN,
                        "org.freedesktop.machine1.manage-images",
                        NULL,
                        false,
                        UID_INVALID,
                        &m->polkit_registry,
                        error);
        if (r < 0)
                return r;
        if (r == 0)
                return 1; /* Will call us back */

        if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
                return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");

        child = fork();
        if (child < 0)
                return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
        if (child == 0) {
                errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);

                r = image_remove(image);
                if (r < 0) {
                        (void) write(errno_pipe_fd[1], &r, sizeof(r));
                        _exit(EXIT_FAILURE);
                }

                _exit(EXIT_SUCCESS);
        }

        errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);

        r = operation_new(m, NULL, child, message, errno_pipe_fd[0]);
        if (r < 0) {
                (void) sigkill_wait(child);
                return r;
        }

        errno_pipe_fd[0] = -1;

        return 1;
}
Esempio n. 11
0
int bus_image_acquire(
                Manager *m,
                sd_bus_message *message,
                const char *name_or_path,
                Image *image,
                ImageAcquireMode mode,
                const char *polkit_action,
                Image **ret,
                sd_bus_error *error) {

        _cleanup_(image_unrefp) Image *loaded = NULL;
        Image *cached;
        int r;

        assert(m);
        assert(message);
        assert(name_or_path || image);
        assert(mode >= 0);
        assert(mode < _BUS_IMAGE_ACQUIRE_MODE_MAX);
        assert(polkit_action || mode == BUS_IMAGE_REFUSE_BY_PATH);
        assert(ret);

        /* Acquires an 'Image' object if not acquired yet, and enforces necessary authentication while doing so. */

        if (mode == BUS_IMAGE_AUTHENTICATE_ALL) {
                r = bus_verify_polkit_async(
                                message,
                                CAP_SYS_ADMIN,
                                polkit_action,
                                NULL,
                                false,
                                UID_INVALID,
                                &m->polkit_registry,
                                error);
                if (r < 0)
                        return r;
                if (r == 0) { /* Will call us back */
                        *ret = NULL;
                        return 0;
                }
        }

        /* Already passed in? */
        if (image) {
                *ret = image;
                return 1;
        }

        /* Let's see if this image is already cached? */
        cached = manager_image_cache_get(m, name_or_path);
        if (cached) {
                *ret = cached;
                return 1;
        }

        if (image_name_is_valid(name_or_path)) {

                /* If it's a short name, let's search for it */
                r = image_find(IMAGE_PORTABLE, name_or_path, &loaded);
                if (r == -ENOENT)
                        return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PORTABLE_IMAGE, "No image '%s' found.", name_or_path);

                /* other errors are handled below… */
        } else {
                /* Don't accept path if this is always forbidden */
                if (mode == BUS_IMAGE_REFUSE_BY_PATH)
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Expected image name, not path in place of '%s'.", name_or_path);

                if (!path_is_absolute(name_or_path))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is not valid or not a valid path.", name_or_path);

                if (!path_is_normalized(name_or_path))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image path '%s' is not normalized.", name_or_path);

                if (mode == BUS_IMAGE_AUTHENTICATE_BY_PATH) {
                        r = bus_verify_polkit_async(
                                        message,
                                        CAP_SYS_ADMIN,
                                        polkit_action,
                                        NULL,
                                        false,
                                        UID_INVALID,
                                        &m->polkit_registry,
                                        error);
                        if (r < 0)
                                return r;
                        if (r == 0) { /* Will call us back */
                                *ret = NULL;
                                return 0;
                        }
                }

                r = image_from_path(name_or_path, &loaded);
        }
        if (r == -EMEDIUMTYPE) {
                sd_bus_error_setf(error, BUS_ERROR_BAD_PORTABLE_IMAGE_TYPE, "Typ of image '%s' not recognized; supported image types are directories/btrfs subvolumes, block devices, and raw disk image files with suffix '.raw'.", name_or_path);
                return r;
        }
        if (r < 0)
                return r;

        /* Add what we just loaded to the cache. This has as side-effect that the object stays in memory until the
         * cache is purged again, i.e. at least for the current event loop iteration, which is all we need, and which
         * means we don't actually need to ref the return object. */
        r = manager_image_cache_add(m, loaded);
        if (r < 0)
                return r;

        *ret = loaded;
        return 1;
}