Example #1
0
static int get_creds(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
        _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
        const char *name;
        int r;

        assert(bus);
        assert(m);
        assert(_creds);

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

        assert_return(service_name_is_valid(name), -EINVAL);

        r = sd_bus_get_owner(bus, name, mask, &c);
        if (r == -ENOENT || r == -ENXIO)
                return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
        if (r < 0)
                return r;

        if ((c->mask & mask) != mask)
                return -ENOTSUP;

        *_creds = c;
        c = NULL;

        return 0;
}
Example #2
0
_public_ int sd_bus_match_signal_async(
                sd_bus *bus,
                sd_bus_slot **ret,
                const char *sender,
                const char *path,
                const char *interface,
                const char *member,
                sd_bus_message_handler_t callback,
                sd_bus_message_handler_t install_callback,
                void *userdata) {

        const char *expression;

        assert_return(bus, -EINVAL);
        assert_return(bus = bus_resolve(bus), -ENOPKG);
        assert_return(!bus_pid_changed(bus), -ECHILD);
        assert_return(!sender || service_name_is_valid(sender), -EINVAL);
        assert_return(!path || object_path_is_valid(path), -EINVAL);
        assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
        assert_return(!member || member_name_is_valid(member), -EINVAL);

        expression = make_expression(sender, path, interface, member);

        return sd_bus_add_match_async(bus, ret, expression, callback, install_callback, userdata);
}
Example #3
0
_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
        _cleanup_free_ char *n = NULL;
        const char *match;
        int r;

        assert_return(track, -EINVAL);
        assert_return(service_name_is_valid(name), -EINVAL);

        r = hashmap_ensure_allocated(&track->names, &string_hash_ops);
        if (r < 0)
                return r;

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

        /* First, subscribe to this name */
        match = MATCH_FOR_NAME(n);
        r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track);
        if (r < 0)
                return r;

        r = hashmap_put(track->names, n, slot);
        if (r == -EEXIST)
                return 0;
        if (r < 0)
                return r;

        /* Second, check if it is currently existing, or maybe
         * doesn't, or maybe disappeared already. */
        r = sd_bus_get_name_creds(track->bus, n, 0, NULL);
        if (r < 0) {
                hashmap_remove(track->names, n);
                return r;
        }

        n = NULL;
        slot = NULL;

        bus_track_remove_from_queue(track);
        track->modified = true;

        return 1;
}
static int busname_verify(BusName *n) {
        char *e;

        assert(n);

        if (UNIT(n)->load_state != UNIT_LOADED)
                return 0;

        if (!service_name_is_valid(n->name)) {
                log_unit_error(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
                return -EINVAL;
        }

        e = strjoina(n->name, ".busname");
        if (!unit_has_name(UNIT(n), e)) {
                log_unit_error(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
                return -EINVAL;
        }

        return 0;
}
Example #5
0
static int driver_list_queued_owners(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
        struct kdbus_cmd_name_list cmd = {};
        struct kdbus_name_list *name_list;
        struct kdbus_cmd_name *name;
        _cleanup_strv_free_ char **owners = NULL;
        char *arg0;
        int r;

        r = sd_bus_message_read(m, "s", &arg0);
        if (r < 0)
                return r;

        assert_return(service_name_is_valid(arg0), -EINVAL);

        cmd.flags = KDBUS_NAME_LIST_QUEUED;

        r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
        if (r < 0)
                return -errno;

        name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);

        KDBUS_ITEM_FOREACH(name, name_list, names) {
                char *n;

                if (name->size <= sizeof(*name))
                        continue;

                if (!streq(name->name, arg0))
                        continue;

                if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0)
                        return -ENOMEM;

                r = strv_push(&owners, n);
                if (r < 0) {
                        free(n);
                        return -ENOMEM;
                }
        }
Example #6
0
static int add_dbus(const char *path, const char *fname, const char *type) {
        _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL;

        const ConfigTableItem table[] = {
                { "D-BUS Service", "Name", config_parse_string, 0, &name },
                { "D-BUS Service", "Exec", config_parse_string, 0, &exec },
                { "D-BUS Service", "User", config_parse_string, 0, &user },
                { "D-BUS Service", "SystemdService", config_parse_string, 0, &service },
                { },
        };

        char *p;
        int r;

        assert(path);
        assert(fname);

        p = strjoina(path, "/", fname);
        r = config_parse(NULL, p, NULL,
                         "D-BUS Service\0",
                         config_item_table_lookup, table,
                         true, false, true, NULL);
        if (r < 0)
                return r;

        if (!name) {
                log_warning("Activation file %s lacks name setting, ignoring.", p);
                return 0;
        }

        if (!service_name_is_valid(name)) {
                log_warning("Bus service name %s is not valid, ignoring.", name);
                return 0;
        }

        if (streq(name, "org.freedesktop.systemd1")) {
                log_debug("Skipping %s, identified as systemd.", p);
                return 0;
        }

        if (service) {
                if (!unit_name_is_valid(service, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
                        log_warning("Unit name %s is not valid, ignoring.", service);
                        return 0;
                }
                if (!endswith(service, ".service")) {
                        log_warning("Bus names can only activate services, ignoring %s.", p);
                        return 0;
                }
        } else {
                if (streq(exec, "/bin/false") || !exec) {
                        log_warning("Neither service name nor binary path specified, ignoring %s.", p);
                        return 0;
                }

                if (exec[0] != '/') {
                        log_warning("Exec= in %s does not start with an absolute path, ignoring.", p);
                        return 0;
                }
        }

        return create_dbus_files(p, name, service, exec, user, type);
}
static int add_dbus(const char *path, const char *fname, const char *type) {
        _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL;

        ConfigTableItem table[] = {
                { "D-BUS Service", "Name", config_parse_string, 0, &name },
                { "D-BUS Service", "Exec", config_parse_string, 0, &exec },
                { "D-BUS Service", "User", config_parse_string, 0, &user },
                { "D-BUS Service", "SystemdService", config_parse_string, 0, &service },
        };

        _cleanup_fclose_ FILE *f = NULL;
        _cleanup_free_ char *p = NULL;
        int r;

        assert(path);
        assert(fname);

        p = strjoin(path, "/", fname, NULL);
        if (!p)
                return log_oom();

        f = fopen(p, "re");
        if (!f) {
                if (errno == -ENOENT)
                        return 0;

                log_error("Failed to read %s: %m", p);
                return -errno;
        }

        r = config_parse(NULL, p, f, "D-BUS Service\0", config_item_table_lookup, table, true, false, NULL);
        if (r < 0)
                return r;

        if (!name) {
                log_warning("Activation file %s lacks name setting, ignoring.", p);
                return 0;
        }

        if (!service_name_is_valid(name)) {
                log_warning("Bus service name %s is not valid, ignoring.", name);
                return 0;
        }

        if (streq(name, "org.freedesktop.systemd1")) {
                log_debug("Skipping %s, identified as systemd.", p);
                return 0;
        }

        if (service) {
                if (!unit_name_is_valid(service, TEMPLATE_INVALID)) {
                        log_warning("Unit name %s is not valid, ignoring.", service);
                        return 0;
                }
                if (!endswith(service, ".service")) {
                        log_warning("Bus names can only activate services, ignoring %s.", p);
                        return 0;
                }
        } else {
                if (streq(exec, "/bin/false") || !exec) {
                        log_warning("Neither service name nor binary path specified, ignoring %s.", p);
                        return 0;
                }

                if (exec[0] != '/') {
                        log_warning("Exec= in %s does not start with an absolute path, ignoring.", p);
                        return 0;
                }
        }

        return create_dbus_files(p, name, service, exec, user, type);
}
Example #8
0
        r = sd_bus_message_read(message, "sss", &name, &old, &new);
        if (r < 0)
                return 0;

        bus_track_remove_name_fully(track, name);
        return 0;
}

_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
        _cleanup_(track_item_freep) struct track_item *n = NULL;
        struct track_item *i;
        const char *match;
        int r;

        assert_return(track, -EINVAL);
        assert_return(service_name_is_valid(name), -EINVAL);

        i = hashmap_get(track->names, name);
        if (i) {
                if (track->recursive) {
                        unsigned k = track->n_ref + 1;

                        if (k < track->n_ref) /* Check for overflow */
                                return -EOVERFLOW;

                        track->n_ref = k;
                }

                bus_track_remove_from_queue(track);
                return 0;
        }
Example #9
0
static int bus_scope_set_transient_property(
                Scope *s,
                const char *name,
                sd_bus_message *message,
                UnitSetPropertiesMode mode,
                sd_bus_error *error) {

        int r;

        assert(s);
        assert(name);
        assert(message);

        if (streq(name, "PIDs")) {
                unsigned n = 0;
                uint32_t pid;

                r = sd_bus_message_enter_container(message, 'a', "u");
                if (r < 0)
                        return r;

                while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {

                        if (pid <= 1)
                                return -EINVAL;

                        if (mode != UNIT_CHECK) {
                                r = unit_watch_pid(UNIT(s), pid);
                                if (r < 0 && r != -EEXIST)
                                        return r;
                        }

                        n++;
                }
                if (r < 0)
                        return r;

                r = sd_bus_message_exit_container(message);
                if (r < 0)
                        return r;

                if (n <= 0)
                        return -EINVAL;

                return 1;

        } else if (streq(name, "Controller")) {
                const char *controller;
                char *c;

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

                if (!isempty(controller) && !service_name_is_valid(controller))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);

                if (mode != UNIT_CHECK) {
                        if (isempty(controller))
                                c = NULL;
                        else {
                                c = strdup(controller);
                                if (!c)
                                        return -ENOMEM;
                        }

                        free(s->controller);
                        s->controller = c;
                }

                return 1;

        } else if (streq(name, "TimeoutStopUSec")) {

                if (mode != UNIT_CHECK) {
                        r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
                        if (r < 0)
                                return r;

                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) s->timeout_stop_usec);
                } else {
                        r = sd_bus_message_skip(message, "t");
                        if (r < 0)
                                return r;
                }

                return 1;
        }

        return 0;
}
Example #10
0
static int bus_scope_set_transient_property(
                Scope *s,
                const char *name,
                sd_bus_message *message,
                UnitWriteFlags flags,
                sd_bus_error *error) {

        int r;

        assert(s);
        assert(name);
        assert(message);

        flags |= UNIT_PRIVATE;

        if (streq(name, "TimeoutStopUSec"))
                return bus_set_transient_usec(UNIT(s), name, &s->timeout_stop_usec, message, flags, error);

        if (streq(name, "PIDs")) {
                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
                unsigned n = 0;

                r = sd_bus_message_enter_container(message, 'a', "u");
                if (r < 0)
                        return r;

                for (;;) {
                        uint32_t upid;
                        pid_t pid;

                        r = sd_bus_message_read(message, "u", &upid);
                        if (r < 0)
                                return r;
                        if (r == 0)
                                break;

                        if (upid == 0) {
                                if (!creds) {
                                        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
                                        if (r < 0)
                                                return r;
                                }

                                r = sd_bus_creds_get_pid(creds, &pid);
                                if (r < 0)
                                        return r;
                        } else
                                pid = (uid_t) upid;

                        r = unit_pid_attachable(UNIT(s), pid, error);
                        if (r < 0)
                                return r;

                        if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                                r = unit_watch_pid(UNIT(s), pid);
                                if (r < 0 && r != -EEXIST)
                                        return r;
                        }

                        n++;
                }

                r = sd_bus_message_exit_container(message);
                if (r < 0)
                        return r;

                if (n <= 0)
                        return -EINVAL;

                return 1;

        } else if (streq(name, "Controller")) {
                const char *controller;

                /* We can't support direct connections with this, as direct connections know no service or unique name
                 * concept, but the Controller field stores exactly that. */
                if (sd_bus_message_get_bus(message) != UNIT(s)->manager->api_bus)
                        return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Sorry, Controller= logic only supported via the bus.");

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

                if (!isempty(controller) && !service_name_is_valid(controller))
                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);

                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
                        r = free_and_strdup(&s->controller, empty_to_null(controller));
                        if (r < 0)
                                return r;
                }

                return 1;
        }

        return 0;
}