Ejemplo n.º 1
0
void lvmnotify_send(struct cmd_context *cmd)
{
	static const char _dbus_notification_failed_msg[] = "D-Bus notification failed";
	sd_bus *bus = NULL;
	sd_bus_message *m = NULL;
	sd_bus_error error = SD_BUS_ERROR_NULL;
	const char *cmd_name;
	int ret;
	int result = 0;

	if (!cmd->vg_notify && !cmd->lv_notify && !cmd->pv_notify)
		return;

	cmd->vg_notify = 0;
	cmd->lv_notify = 0;
	cmd->pv_notify = 0;

	cmd_name = get_cmd_name();

	ret = sd_bus_open_system(&bus);
	if (ret < 0) {
		log_debug_dbus("Failed to connect to dbus: %d", ret);
		return;
	}

	log_debug_dbus("Nofify dbus at %s.", LVM_DBUS_DESTINATION);

	ret = sd_bus_call_method(bus,
				 LVM_DBUS_DESTINATION,
				 LVM_DBUS_PATH,
				 LVM_DBUS_INTERFACE,
				 "ExternalEvent",
				 &error,
				 &m,
				 "s",
				 cmd_name);

	if (ret < 0) {
		if (sd_bus_error_has_name(&error, SD_BUS_SYSTEMD_NO_SUCH_UNIT_ERROR) ||
		    sd_bus_error_has_name(&error, SD_BUS_DBUS_SERVICE_UNKNOWN_ERROR))
			log_debug_dbus("%s: %s", _dbus_notification_failed_msg, error.message);
		else
			log_warn("WARNING: %s: %s", _dbus_notification_failed_msg, error.message);
		goto out;
	}

	ret = sd_bus_message_read(m, "i", &result);
	if (ret < 0)
		log_debug_dbus("Failed to parse dbus response message: %d", ret);
	if (result)
		log_debug_dbus("Bad return value from dbus service: %d", result);
out:
	sd_bus_error_free(&error);
	sd_bus_message_unref(m);
	sd_bus_flush_close_unref(bus);
}
static void test_rr_lookup(sd_bus *bus, const char *name, uint16_t type, const char *result) {
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_free_ char *m = NULL;
        int r;

        /* If the name starts with a dot, we prefix one to three random labels */
        if (startswith(name, ".")) {
                prefix_random(name + 1, &m);
                name = m;
        }

        assert_se(sd_bus_message_new_method_call(
                                  bus,
                                  &req,
                                  "org.freedesktop.resolve1",
                                  "/org/freedesktop/resolve1",
                                  "org.freedesktop.resolve1.Manager",
                                  "ResolveRecord") >= 0);

        assert_se(sd_bus_message_append(req, "isqqt", 0, name, DNS_CLASS_IN, type, UINT64_C(0)) >= 0);

        r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);

        if (r < 0) {
                assert_se(result);
                assert_se(sd_bus_error_has_name(&error, result));
                log_info("[OK] %s/%s resulted in <%s>.", name, dns_type_to_string(type), error.name);
        } else {
                assert_se(!result);
                log_info("[OK] %s/%s succeeded.", name, dns_type_to_string(type));
        }
}
Ejemplo n.º 3
0
static void start_target(const char *target, const char *mode) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        int r;

        assert(target);

        r = bus_connect_system_systemd(&bus);
        if (r < 0) {
                log_error_errno(r, "Failed to get D-Bus connection: %m");
                return;
        }

        log_info("Running request %s/start/replace", target);

        /* Start these units only if we can replace base.target with it */
        r = sd_bus_call_method(bus,
                               "org.freedesktop.systemd1",
                               "/org/freedesktop/systemd1",
                               "org.freedesktop.systemd1.Manager",
                               "StartUnitReplace",
                               &error,
                               NULL,
                               "sss", "basic.target", target, mode);

        /* Don't print a warning if we aren't called during startup */
        if (r < 0 && !sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB))
                log_error("Failed to start unit: %s", bus_error_message(&error, r));
}
static void test_hostname_lookup(sd_bus *bus, const char *name, int family, const char *result) {
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_free_ char *m = NULL;
        const char *af;
        int r;

        af = family == AF_UNSPEC ? "AF_UNSPEC" : af_to_name(family);

        /* If the name starts with a dot, we prefix one to three random labels */
        if (startswith(name, ".")) {
                prefix_random(name + 1, &m);
                name = m;
        }

        assert_se(sd_bus_message_new_method_call(
                                  bus,
                                  &req,
                                  "org.freedesktop.resolve1",
                                  "/org/freedesktop/resolve1",
                                  "org.freedesktop.resolve1.Manager",
                                  "ResolveHostname") >= 0);

        assert_se(sd_bus_message_append(req, "isit", 0, name, family, UINT64_C(0)) >= 0);

        r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);

        if (r < 0) {
                assert_se(result);
                assert_se(sd_bus_error_has_name(&error, result));
                log_info("[OK] %s/%s resulted in <%s>.", name, af, error.name);
        } else {
                assert_se(!result);
                log_info("[OK] %s/%s succeeded.", name, af);
        }

}
Ejemplo n.º 5
0
enum nss_status _nss_resolve_gethostbyname4_r(
                const char *name,
                struct gaih_addrtuple **pat,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        const char *canonical = NULL;
        size_t l, ms, idx;
        char *r_name;
        int c, r, i = 0;

        assert(name);
        assert(pat);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
                        *errnop = ESRCH;
                        *h_errnop = HOST_NOT_FOUND;
                        return NSS_STATUS_NOTFOUND;
                }

                if (bus_error_shall_fallback(&error)) {

                        enum nss_status (*fallback)(
                                        const char *name,
                                        struct gaih_addrtuple **pat,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp);

                        fallback = (enum nss_status (*)(const char *name,
                                                        struct gaih_addrtuple **pat,
                                                        char *buffer, size_t buflen,
                                                        int *errnop, int *h_errnop,
                                                        int32_t *ttlp))
                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
                        if (fallback)
                                return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
                }

                *errnop = -r;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        c = count_addresses(reply, AF_UNSPEC, &canonical);
        if (c < 0) {
                r = c;
                goto fail;
        }
        if (c == 0) {
                *errnop = ESRCH;
                *h_errnop = HOST_NOT_FOUND;
                return NSS_STATUS_NOTFOUND;
        }

        if (isempty(canonical))
                canonical = name;

        l = strlen(canonical);
        ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
        if (buflen < ms) {
                *errnop = ENOMEM;
                *h_errnop = TRY_AGAIN;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, append name */
        r_name = buffer;
        memcpy(r_name, canonical, l+1);
        idx = ALIGN(l+1);

        /* Second, append addresses */
        r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                int family, ifindex;
                const void *a;
                size_t sz;

                assert_cc(sizeof(int32_t) == sizeof(int));

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        goto fail;

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        goto fail;

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        goto fail;

                if (!IN_SET(family, AF_INET, AF_INET6))
                        continue;

                if (sz != FAMILY_ADDRESS_SIZE(family)) {
                        r = -EINVAL;
                        goto fail;
                }

                r_tuple = (struct gaih_addrtuple*) (buffer + idx);
                r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
                r_tuple->name = r_name;
                r_tuple->family = family;
                r_tuple->scopeid = ifindex;
                memcpy(r_tuple->addr, a, sz);

                idx += ALIGN(sizeof(struct gaih_addrtuple));
                i++;
        }
        if (r < 0)
                goto fail;

        assert(i == c);
        assert(idx == ms);

        if (*pat)
                **pat = *r_tuple_first;
        else
                *pat = r_tuple_first;

        if (ttlp)
                *ttlp = 0;

        /* Explicitly reset all error variables */
        *errnop = 0;
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_DATA;
        return NSS_STATUS_UNAVAIL;
}
Ejemplo n.º 6
0
static int client(struct context *c) {
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
        _cleanup_bus_unref_ sd_bus *bus = NULL;
        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
        const char *s;
        int r;

        assert_se(sd_bus_new(&bus) >= 0);
        assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
        assert_se(sd_bus_start(bus) >= 0);

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL);
        assert_se(r >= 0);

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        assert_se(streq(s, "<<<hallo>>>"));

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
        assert_se(r < 0);
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));

        sd_bus_error_free(&error);

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
        assert_se(r < 0);
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));

        sd_bus_error_free(&error);

        r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        assert_se(streq(s, "<<<hallo>>>"));

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
        assert_se(r >= 0);

        r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        assert_se(streq(s, "test"));

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
        assert_se(r >= 0);

        assert_se(c->automatic_integer_property == 815);

        r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
        assert_se(r >= 0);

        assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        fputs(s, stdout);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        log_info("read %s", s);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        fputs(s, stdout);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        fputs(s, stdout);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
        assert_se(r >= 0);

        r = sd_bus_message_read(reply, "s", &s);
        assert_se(r >= 0);
        fputs(s, stdout);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
        assert_se(r >= 0);

        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
        assert_se(r < 0);
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
        sd_bus_error_free(&error);

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
        assert_se(r < 0);
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
        sd_bus_error_free(&error);

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
        assert_se(r >= 0);

        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
        assert_se(r >= 0);

        r = sd_bus_process(bus, &reply);
        assert_se(r > 0);

        assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, "");
        assert_se(r >= 0);

        r = sd_bus_process(bus, &reply);
        assert_se(r > 0);

        assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, "");
        assert_se(r >= 0);

        r = sd_bus_process(bus, &reply);
        assert_se(r > 0);

        assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, "");
        assert_se(r >= 0);

        r = sd_bus_process(bus, &reply);
        assert_se(r > 0);

        assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, "");
        assert_se(r >= 0);

        r = sd_bus_process(bus, &reply);
        assert_se(r > 0);

        assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, "");
        assert_se(r >= 0);

        r = sd_bus_process(bus, &reply);
        assert_se(r > 0);

        assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
        bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);

        sd_bus_message_unref(reply);
        reply = NULL;

        r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
        assert_se(r >= 0);

        sd_bus_flush(bus);

        return 0;
}
Ejemplo n.º 7
0
int bus_test_polkit(
                sd_bus_message *call,
                int capability,
                const char *action,
                const char **details,
                uid_t good_user,
                bool *_challenge,
                sd_bus_error *e) {

        int r;

        assert(call);
        assert(action);

        /* Tests non-interactively! */

        r = check_good_user(call, good_user);
        if (r != 0)
                return r;

        r = sd_bus_query_sender_privilege(call, capability);
        if (r < 0)
                return r;
        else if (r > 0)
                return 1;
#ifdef ENABLE_POLKIT
        else {
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                int authorized = false, challenge = false;
                const char *sender, **k, **v;

                sender = sd_bus_message_get_sender(call);
                if (!sender)
                        return -EBADMSG;

                r = sd_bus_message_new_method_call(
                                call->bus,
                                &request,
                                "org.freedesktop.PolicyKit1",
                                "/org/freedesktop/PolicyKit1/Authority",
                                "org.freedesktop.PolicyKit1.Authority",
                                "CheckAuthorization");
                if (r < 0)
                        return r;

                r = sd_bus_message_append(
                                request,
                                "(sa{sv})s",
                                "system-bus-name", 1, "name", "s", sender,
                                action);
                if (r < 0)
                        return r;

                r = sd_bus_message_open_container(request, 'a', "{ss}");
                if (r < 0)
                        return r;

                STRV_FOREACH_PAIR(k, v, details) {
                        r = sd_bus_message_append(request, "{ss}", *k, *v);
                        if (r < 0)
                                return r;
                }

                r = sd_bus_message_close_container(request);
                if (r < 0)
                        return r;

                r = sd_bus_message_append(request, "us", 0, NULL);
                if (r < 0)
                        return r;

                r = sd_bus_call(call->bus, request, 0, e, &reply);
                if (r < 0) {
                        /* Treat no PK available as access denied */
                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
                                sd_bus_error_free(e);
                                return -EACCES;
                        }

                        return r;
                }

                r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
                if (r < 0)
                        return r;

                r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
                if (r < 0)
                        return r;

                if (authorized)
                        return 1;

                if (_challenge) {
                        *_challenge = challenge;
                        return 0;
                }
        }
Ejemplo n.º 8
0
int main(int argc, char *argv[]) {

    _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
    const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
    const sd_bus_error temporarily_const_error = {
        .name = SD_BUS_ERROR_ACCESS_DENIED,
        .message = "oh! no",
        ._need_free = -1
    };

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -ENOTSUP);
    assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED));
    assert_se(streq(error.message, "xxx"));
    assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED));
    assert_se(sd_bus_error_get_errno(&error) == ENOTSUP);
    assert_se(sd_bus_error_is_set(&error));
    sd_bus_error_free(&error);

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
    assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
    assert_se(streq(error.message, "yyy -1"));
    assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
    assert_se(sd_bus_error_get_errno(&error) == ENOENT);
    assert_se(sd_bus_error_is_set(&error));

    assert_se(!sd_bus_error_is_set(&second));
    assert_se(second._need_free == 0);
    assert_se(error._need_free > 0);
    assert_se(sd_bus_error_copy(&second, &error) == -ENOENT);
    assert_se(second._need_free > 0);
    assert_se(streq(error.name, second.name));
    assert_se(streq(error.message, second.message));
    assert_se(sd_bus_error_get_errno(&second) == ENOENT);
    assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND));
    assert_se(sd_bus_error_is_set(&second));

    sd_bus_error_free(&error);
    sd_bus_error_free(&second);

    assert_se(!sd_bus_error_is_set(&second));
    assert_se(const_error._need_free == 0);
    assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST);
    assert_se(second._need_free == 0);
    assert_se(streq(const_error.name, second.name));
    assert_se(streq(const_error.message, second.message));
    assert_se(sd_bus_error_get_errno(&second) == EEXIST);
    assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS));
    assert_se(sd_bus_error_is_set(&second));
    sd_bus_error_free(&second);

    assert_se(!sd_bus_error_is_set(&second));
    assert_se(temporarily_const_error._need_free < 0);
    assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES);
    assert_se(second._need_free > 0);
    assert_se(streq(temporarily_const_error.name, second.name));
    assert_se(streq(temporarily_const_error.message, second.message));
    assert_se(sd_bus_error_get_errno(&second) == EACCES);
    assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED));
    assert_se(sd_bus_error_is_set(&second));

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN);
    assert_se(streq(error.name, "System.Error.EUCLEAN"));
    assert_se(streq(error.message, "Hallo"));
    assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN"));
    assert_se(sd_bus_error_get_errno(&error) == EUCLEAN);
    assert_se(sd_bus_error_is_set(&error));
    sd_bus_error_free(&error);

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
    assert_se(streq(error.name, "System.Error.EBUSY"));
    assert_se(streq(error.message, strerror(EBUSY)));
    assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
    assert_se(sd_bus_error_get_errno(&error) == EBUSY);
    assert_se(sd_bus_error_is_set(&error));
    sd_bus_error_free(&error);

    assert_se(!sd_bus_error_is_set(&error));
    assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO);
    assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR));
    assert_se(streq(error.message, "Waldi X"));
    assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
    assert_se(sd_bus_error_get_errno(&error) == EIO);
    assert_se(sd_bus_error_is_set(&error));

    return 0;
}
Ejemplo n.º 9
0
enum nss_status _nss_resolve_gethostbyaddr2_r(
                const void* addr, socklen_t len,
                int af,
                struct hostent *result,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        char *r_name, *r_aliases, *r_addr, *r_addr_list;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        enum nss_status ret = NSS_STATUS_UNAVAIL;
        unsigned c = 0, i = 0;
        size_t ms = 0, idx;
        const char *n;
        int r, ifindex;

        PROTECT_ERRNO;
        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

        assert(addr);
        assert(result);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        if (!IN_SET(af, AF_INET, AF_INET6)) {
                *errnop = EAFNOSUPPORT;
                *h_errnop = NO_DATA;
                return NSS_STATUS_UNAVAIL;
        }

        if (len != FAMILY_ADDRESS_SIZE(af)) {
                *errnop = EINVAL;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        if (avoid_deadlock()) {
                r = -EDEADLK;
                goto fail;
        }

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveAddress");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "ii", 0, af);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append_array(req, 'y', addr, len);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "t", (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") ||
                    !bus_error_shall_fallback(&error))
                        goto not_found;

                goto fail;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(is)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                c++;
                ms += ALIGN(strlen(n) + 1);
        }
        if (r < 0)
                goto fail;

        r = sd_bus_message_rewind(reply, false);
        if (r < 0)
                return r;

        if (c <= 0)
                goto not_found;

        ms += ALIGN(len) +              /* the address */
              2 * sizeof(char*) +       /* pointers to the address, plus trailing NULL */
              c * sizeof(char*);        /* pointers to aliases, plus trailing NULL */

        if (buflen < ms) {
                *errnop = ERANGE;
                *h_errnop = NETDB_INTERNAL;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, place address */
        r_addr = buffer;
        memcpy(r_addr, addr, len);
        idx = ALIGN(len);

        /* Second, place address list */
        r_addr_list = buffer + idx;
        ((char**) r_addr_list)[0] = r_addr;
        ((char**) r_addr_list)[1] = NULL;
        idx += sizeof(char*) * 2;

        /* Third, reserve space for the aliases array */
        r_aliases = buffer + idx;
        idx += sizeof(char*) * c;

        /* Fourth, place aliases */
        i = 0;
        r_name = buffer + idx;
        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
                char *p;
                size_t l;

                l = strlen(n);
                p = buffer + idx;
                memcpy(p, n, l+1);

                if (i > 0)
                        ((char**) r_aliases)[i-1] = p;
                i++;

                idx += ALIGN(l+1);
        }
        if (r < 0)
                goto fail;

        ((char**) r_aliases)[c-1] = NULL;
        assert(idx == ms);

        result->h_name = r_name;
        result->h_aliases = (char**) r_aliases;
        result->h_addrtype = af;
        result->h_length = len;
        result->h_addr_list = (char**) r_addr_list;

        if (ttlp)
                *ttlp = 0;

        /* Explicitly reset both *h_errnop and h_errno to work around
         * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_RECOVERY;
        return ret;

not_found:
        *h_errnop = HOST_NOT_FOUND;
        return NSS_STATUS_NOTFOUND;
}
Ejemplo n.º 10
0
int bus_verify_polkit_async(
                sd_bus_message *call,
                int capability,
                const char *action,
                bool interactive,
                Hashmap **registry,
                sd_bus_error *error) {

#ifdef ENABLE_POLKIT
        _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
        AsyncPolkitQuery *q;
        const char *sender;
        sd_bus_message_handler_t callback;
        void *userdata;
#endif
        int r;

        assert(call);
        assert(action);
        assert(registry);

#ifdef ENABLE_POLKIT
        q = hashmap_get(*registry, call);
        if (q) {
                int authorized, challenge;

                /* This is the second invocation of this function, and
                 * there's already a response from polkit, let's
                 * process it */
                assert(q->reply);

                if (sd_bus_message_is_method_error(q->reply, NULL)) {
                        const sd_bus_error *e;

                        /* Copy error from polkit reply */
                        e = sd_bus_message_get_error(q->reply);
                        sd_bus_error_copy(error, e);

                        /* Treat no PK available as access denied */
                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
                                return -EACCES;

                        return -sd_bus_error_get_errno(e);
                }

                r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
                if (r >= 0)
                        r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);

                if (r < 0)
                        return r;

                if (authorized)
                        return 1;

                return -EACCES;
        }
#endif

        r = sd_bus_query_sender_privilege(call, capability);
        if (r < 0)
                return r;
        else if (r > 0)
                return 1;

#ifdef ENABLE_POLKIT
        if (sd_bus_get_current_message(call->bus) != call)
                return -EINVAL;

        callback = sd_bus_get_current_handler(call->bus);
        if (!callback)
                return -EINVAL;

        userdata = sd_bus_get_current_userdata(call->bus);

        sender = sd_bus_message_get_sender(call);
        if (!sender)
                return -EBADMSG;

        r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
        if (r < 0)
                return r;

        r = sd_bus_message_new_method_call(
                        call->bus,
                        &pk,
                        "org.freedesktop.PolicyKit1",
                        "/org/freedesktop/PolicyKit1/Authority",
                        "org.freedesktop.PolicyKit1.Authority",
                        "CheckAuthorization");
        if (r < 0)
                return r;

        r = sd_bus_message_append(
                        pk,
                        "(sa{sv})sa{ss}us",
                        "system-bus-name", 1, "name", "s", sender,
                        action,
                        0,
                        interactive ? 1 : 0,
                        NULL);
        if (r < 0)
                return r;

        q = new0(AsyncPolkitQuery, 1);
        if (!q)
                return -ENOMEM;

        q->request = sd_bus_message_ref(call);
        q->callback = callback;
        q->userdata = userdata;

        r = hashmap_put(*registry, call, q);
        if (r < 0) {
                async_polkit_query_free(q);
                return r;
        }

        q->registry = *registry;

        r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
        if (r < 0) {
                async_polkit_query_free(q);
                return r;
        }

        return 0;
#endif

        return -EACCES;
}
Ejemplo n.º 11
0
static bool bus_error_shall_fallback(sd_bus_error *e) {
        return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
               sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) ||
               sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) ||
               sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED);
}
Ejemplo n.º 12
0
enum nss_status _nss_systemd_getgrgid_r(
                gid_t gid,
                struct group *gr,
                char *buffer, size_t buflen,
                int *errnop) {

        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        const char *translated;
        size_t l;
        int r;

        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

        if (!gid_is_valid(gid)) {
                r = -EINVAL;
                goto fail;
        }

        if (gid <= SYSTEM_GID_MAX)
                goto not_found;

        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                goto not_found;

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_call_method(bus,
                               "org.freedesktop.systemd1",
                               "/org/freedesktop/systemd1",
                               "org.freedesktop.systemd1.Manager",
                               "LookupDynamicUserByUID",
                               &error,
                               &reply,
                               "u",
                               (uint32_t) gid);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER))
                        goto not_found;

                goto fail;
        }

        r = sd_bus_message_read(reply, "s", &translated);
        if (r < 0)
                goto fail;

        l = sizeof(char*) + strlen(translated) + 1;
        if (buflen < l) {
                *errnop = ENOMEM;
                return NSS_STATUS_TRYAGAIN;
        }

        memzero(buffer, sizeof(char*));
        strcpy(buffer + sizeof(char*), translated);

        gr->gr_name = buffer + sizeof(char*);
        gr->gr_gid = gid;
        gr->gr_passwd = (char*) "*"; /* locked */
        gr->gr_mem = (char**) buffer;

        *errnop = 0;
        return NSS_STATUS_SUCCESS;

not_found:
        *errnop = 0;
        return NSS_STATUS_NOTFOUND;

fail:
        *errnop = -r;
        return NSS_STATUS_UNAVAIL;
}
Ejemplo n.º 13
0
enum nss_status _nss_systemd_getpwuid_r(
                uid_t uid,
                struct passwd *pwd,
                char *buffer, size_t buflen,
                int *errnop) {

        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        const char *translated;
        size_t l;
        int r;

        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

        if (!uid_is_valid(uid)) {
                r = -EINVAL;
                goto fail;
        }

        if (uid <= SYSTEM_UID_MAX)
                goto not_found;

        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                goto not_found;

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_call_method(bus,
                               "org.freedesktop.systemd1",
                               "/org/freedesktop/systemd1",
                               "org.freedesktop.systemd1.Manager",
                               "LookupDynamicUserByUID",
                               &error,
                               &reply,
                               "u",
                               (uint32_t) uid);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER))
                        goto not_found;

                goto fail;
        }

        r = sd_bus_message_read(reply, "s", &translated);
        if (r < 0)
                goto fail;

        l = strlen(translated) + 1;
        if (buflen < l) {
                *errnop = ENOMEM;
                return NSS_STATUS_TRYAGAIN;
        }

        memcpy(buffer, translated, l);

        pwd->pw_name = buffer;
        pwd->pw_uid = uid;
        pwd->pw_gid = uid;
        pwd->pw_gecos = (char*) "Dynamic User";
        pwd->pw_passwd = (char*) "*"; /* locked */
        pwd->pw_dir = (char*) "/";
        pwd->pw_shell = (char*) "/sbin/nologin";

        *errnop = 0;
        return NSS_STATUS_SUCCESS;

not_found:
        *errnop = 0;
        return NSS_STATUS_NOTFOUND;

fail:
        *errnop = -r;
        return NSS_STATUS_UNAVAIL;
}
Ejemplo n.º 14
0
int main(int argc, char *argv[]) {
        _cleanup_close_ int bus_ref = -1;
        _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *bname = NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        const char *ua = NULL, *ub = NULL, *the_string = NULL;
        sd_bus *a, *b;
        int r, pipe_fds[2];
        const char *nn;

        log_set_max_level(LOG_DEBUG);

        assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0);

        bus_ref = bus_kernel_create_bus(name, false, &bus_name);
        if (bus_ref == -ENOENT)
                return EXIT_TEST_SKIP;

        assert_se(bus_ref >= 0);

        address = strappend("kernel:path=", bus_name);
        assert_se(address);

        r = sd_bus_new(&a);
        assert_se(r >= 0);

        r = sd_bus_new(&b);
        assert_se(r >= 0);

        r = sd_bus_set_description(a, "a");
        assert_se(r >= 0);

        r = sd_bus_set_address(a, address);
        assert_se(r >= 0);

        r = sd_bus_set_address(b, address);
        assert_se(r >= 0);

        assert_se(sd_bus_negotiate_timestamp(a, 1) >= 0);
        assert_se(sd_bus_negotiate_creds(a, true, _SD_BUS_CREDS_ALL) >= 0);

        assert_se(sd_bus_negotiate_timestamp(b, 0) >= 0);
        assert_se(sd_bus_negotiate_creds(b, true, 0) >= 0);

        r = sd_bus_start(a);
        assert_se(r >= 0);

        r = sd_bus_start(b);
        assert_se(r >= 0);

        assert_se(sd_bus_negotiate_timestamp(b, 1) >= 0);
        assert_se(sd_bus_negotiate_creds(b, true, _SD_BUS_CREDS_ALL) >= 0);

        r = sd_bus_get_unique_name(a, &ua);
        assert_se(r >= 0);
        printf("unique a: %s\n", ua);

        r = sd_bus_get_description(a, &nn);
        assert_se(r >= 0);
        printf("name of a: %s\n", nn);

        r = sd_bus_get_unique_name(b, &ub);
        assert_se(r >= 0);
        printf("unique b: %s\n", ub);

        r = sd_bus_get_description(b, &nn);
        assert_se(r >= 0);
        printf("name of b: %s\n", nn);

        assert_se(bus_kernel_get_bus_name(b, &bname) >= 0);
        assert_se(endswith(bname, name));

        r = sd_bus_call_method(a, "this.doesnt.exist", "/foo", "meh.mah", "muh", &error, NULL, "s", "yayayay");
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN));
        assert_se(r == -EHOSTUNREACH);

        r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL);
        assert_se(r >= 0);

        r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name");
        assert_se(r >= 0);

        r = sd_bus_try_close(b);
        assert_se(r == -EBUSY);

        r = sd_bus_process_priority(b, -10, &m);
        assert_se(r == 0);

        r = sd_bus_process(b, &m);
        assert_se(r > 0);
        assert_se(m);

        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
        assert_se(sd_bus_message_rewind(m, true) >= 0);

        r = sd_bus_message_read(m, "s", &the_string);
        assert_se(r >= 0);
        assert_se(streq(the_string, "I am a string"));

        sd_bus_message_unref(m);
        m = NULL;

        r = sd_bus_request_name(a, "net.x0pointer.foobar", 0);
        assert_se(r >= 0);

        r = sd_bus_message_new_method_call(b, &m, "net.x0pointer.foobar", "/a/path", "an.inter.face", "AMethod");
        assert_se(r >= 0);

        assert_se(pipe2(pipe_fds, O_CLOEXEC) >= 0);

        assert_se(write(pipe_fds[1], "x", 1) == 1);

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

        r = sd_bus_message_append(m, "h", pipe_fds[0]);
        assert_se(r >= 0);

        pipe_fds[0] = safe_close(pipe_fds[0]);

        r = sd_bus_send(b, m, NULL);
        assert_se(r >= 0);

        for (;;) {
                sd_bus_message_unref(m);
                m = NULL;
                r = sd_bus_process(a, &m);
                assert_se(r > 0);
                assert_se(m);

                bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
                assert_se(sd_bus_message_rewind(m, true) >= 0);

                if (sd_bus_message_is_method_call(m, "an.inter.face", "AMethod")) {
                        int fd;
                        char x;

                        r = sd_bus_message_read(m, "h", &fd);
                        assert_se(r >= 0);

                        assert_se(read(fd, &x, 1) == 1);
                        assert_se(x == 'x');
                        break;
                }
        }

        r = sd_bus_release_name(a, "net.x0pointer.foobar");
        assert_se(r >= 0);

        r = sd_bus_release_name(a, "net.x0pointer.foobar");
        assert_se(r == -ESRCH);

        r = sd_bus_try_close(a);
        assert_se(r >= 0);

        sd_bus_unref(a);
        sd_bus_unref(b);

        return 0;
}
Ejemplo n.º 15
0
int bus_verify_polkit(
                sd_bus *bus,
                sd_bus_message *m,
                const char *action,
                bool interactive,
                bool *_challenge,
                sd_bus_error *e) {

        const char *sender;
        uid_t uid;
        int r;

        assert(bus);
        assert(m);
        assert(action);

        sender = sd_bus_message_get_sender(m);
        if (!sender)
                return -EBADMSG;

        r = sd_bus_get_owner_uid(bus, sender, &uid);
        if (r < 0)
                return r;

        if (uid == 0)
                return 1;

#ifdef ENABLE_POLKIT
        else {
                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
                unsigned authorized = false, challenge = false;

                r = sd_bus_call_method(
                                bus,
                                "org.freedesktop.PolicyKit1",
                                "/org/freedesktop/PolicyKit1/Authority",
                                "org.freedesktop.PolicyKit1.Authority",
                                "CheckAuthorization",
                                e,
                                &reply,
                                "(sa{sv})sa{ss}us",
                                "system-bus-name", 1, "name", "s", sender,
                                action,
                                0,
                                interactive ? 1 : 0,
                                "");

                if (r < 0) {
                        /* Treat no PK available as access denied */
                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
                                sd_bus_error_free(e);
                                return -EACCES;
                        }

                        return r;
                }

                r = sd_bus_message_read(reply, "(bb)", &authorized, &challenge);
                if (r < 0)
                        return r;

                if (authorized)
                        return 1;

                if (_challenge) {
                        *_challenge = challenge;
                        return 0;
                }
        }
#endif

        return -EACCES;
}
Ejemplo n.º 16
0
enum nss_status _nss_resolve_gethostbyname3_r(
                const char *name,
                int af,
                struct hostent *result,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp,
                char **canonp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        char *r_name, *r_aliases, *r_addr, *r_addr_list;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        size_t l, idx, ms, alen;
        const char *canonical;
        int c, r, i = 0;

        assert(name);
        assert(result);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        if (af == AF_UNSPEC)
                af = AF_INET;

        if (af != AF_INET && af != AF_INET6) {
                r = -EAFNOSUPPORT;
                goto fail;
        }

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
                        *errnop = ESRCH;
                        *h_errnop = HOST_NOT_FOUND;
                        return NSS_STATUS_NOTFOUND;
                }

                if (bus_error_shall_fallback(&error)) {

                        enum nss_status (*fallback)(
                                        const char *name,
                                        int af,
                                        struct hostent *result,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp,
                                        char **canonp);

                        fallback = (enum nss_status (*)(const char *name,
                                                        int af,
                                                        struct hostent *result,
                                                        char *buffer, size_t buflen,
                                                        int *errnop, int *h_errnop,
                                                        int32_t *ttlp,
                                                        char **canonp))
                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
                        if (fallback)
                                return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
                }

                *errnop = -r;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        c = count_addresses(reply, af, &canonical);
        if (c < 0) {
                r = c;
                goto fail;
        }
        if (c == 0) {
                *errnop = ESRCH;
                *h_errnop = HOST_NOT_FOUND;
                return NSS_STATUS_NOTFOUND;
        }

        if (isempty(canonical))
                canonical = name;

        alen = FAMILY_ADDRESS_SIZE(af);
        l = strlen(canonical);

        ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);

        if (buflen < ms) {
                *errnop = ENOMEM;
                *h_errnop = TRY_AGAIN;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, append name */
        r_name = buffer;
        memcpy(r_name, canonical, l+1);
        idx = ALIGN(l+1);

        /* Second, create empty aliases array */
        r_aliases = buffer + idx;
        ((char**) r_aliases)[0] = NULL;
        idx += sizeof(char*);

        /* Third, append addresses */
        r_addr = buffer + idx;

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                int ifindex, family;
                const void *a;
                size_t sz;

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        goto fail;

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        goto fail;

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        goto fail;

                if (family != af)
                        continue;

                if (sz != alen) {
                        r = -EINVAL;
                        goto fail;
                }

                memcpy(r_addr + i*ALIGN(alen), a, alen);
                i++;
        }
        if (r < 0)
                goto fail;

        assert(i == c);
        idx += c * ALIGN(alen);

        /* Fourth, append address pointer array */
        r_addr_list = buffer + idx;
        for (i = 0; i < c; i++)
                ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);

        ((char**) r_addr_list)[i] = NULL;
        idx += (c+1) * sizeof(char*);

        assert(idx == ms);

        result->h_name = r_name;
        result->h_aliases = (char**) r_aliases;
        result->h_addrtype = af;
        result->h_length = alen;
        result->h_addr_list = (char**) r_addr_list;

        /* Explicitly reset all error variables */
        *errnop = 0;
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        if (ttlp)
                *ttlp = 0;

        if (canonp)
                *canonp = r_name;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_DATA;
        return NSS_STATUS_UNAVAIL;
}
Ejemplo n.º 17
0
enum nss_status _nss_resolve_gethostbyaddr2_r(
                const void* addr, socklen_t len,
                int af,
                struct hostent *result,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        char *r_name, *r_aliases, *r_addr, *r_addr_list;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        unsigned c = 0, i = 0;
        size_t ms = 0, idx;
        const char *n;
        int r, ifindex;

        assert(addr);
        assert(result);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        if (!IN_SET(af, AF_INET, AF_INET6)) {
                *errnop = EAFNOSUPPORT;
                *h_errnop = NO_DATA;
                return NSS_STATUS_UNAVAIL;
        }

        if (len != FAMILY_ADDRESS_SIZE(af)) {
                *errnop = EINVAL;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveAddress");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "ii", 0, af);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append_array(req, 'y', addr, len);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "t", (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
                        *errnop = ESRCH;
                        *h_errnop = HOST_NOT_FOUND;
                        return NSS_STATUS_NOTFOUND;
                }

                if (bus_error_shall_fallback(&error)) {

                        enum nss_status (*fallback)(
                                        const void* addr, socklen_t len,
                                        int af,
                                        struct hostent *result,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp);

                        fallback = (enum nss_status (*)(
                                        const void* addr, socklen_t len,
                                        int af,
                                        struct hostent *result,
                                        char *buffer, size_t buflen,
                                        int *errnop, int *h_errnop,
                                        int32_t *ttlp))
                                find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");

                        if (fallback)
                                return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
                }

                *errnop = -r;
                *h_errnop = NO_RECOVERY;
                return NSS_STATUS_UNAVAIL;
        }

        r = sd_bus_message_enter_container(reply, 'a', "(is)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                c++;
                ms += ALIGN(strlen(n) + 1);
        }
        if (r < 0)
                goto fail;

        r = sd_bus_message_rewind(reply, false);
        if (r < 0)
                return r;

        if (c <= 0) {
                *errnop = ESRCH;
                *h_errnop = HOST_NOT_FOUND;
                return NSS_STATUS_NOTFOUND;
        }

        ms += ALIGN(len) +              /* the address */
              2 * sizeof(char*) +       /* pointers to the address, plus trailing NULL */
              c * sizeof(char*);        /* pointers to aliases, plus trailing NULL */

        if (buflen < ms) {
                *errnop = ENOMEM;
                *h_errnop = TRY_AGAIN;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, place address */
        r_addr = buffer;
        memcpy(r_addr, addr, len);
        idx = ALIGN(len);

        /* Second, place address list */
        r_addr_list = buffer + idx;
        ((char**) r_addr_list)[0] = r_addr;
        ((char**) r_addr_list)[1] = NULL;
        idx += sizeof(char*) * 2;

        /* Third, reserve space for the aliases array */
        r_aliases = buffer + idx;
        idx += sizeof(char*) * c;

        /* Fourth, place aliases */
        i = 0;
        r_name = buffer + idx;
        while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
                char *p;
                size_t l;

                l = strlen(n);
                p = buffer + idx;
                memcpy(p, n, l+1);

                if (i > 1)
                        ((char**) r_aliases)[i-1] = p;
                i++;

                idx += ALIGN(l+1);
        }
        if (r < 0)
                goto fail;

        ((char**) r_aliases)[c-1] = NULL;
        assert(idx == ms);

        result->h_name = r_name;
        result->h_aliases = (char**) r_aliases;
        result->h_addrtype = af;
        result->h_length = len;
        result->h_addr_list = (char**) r_addr_list;

        if (ttlp)
                *ttlp = 0;

        /* Explicitly reset all error variables */
        *errnop = 0;
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_DATA;
        return NSS_STATUS_UNAVAIL;
}
Ejemplo n.º 18
0
enum nss_status _nss_systemd_getpwnam_r(
                const char *name,
                struct passwd *pwd,
                char *buffer, size_t buflen,
                int *errnop) {

        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        uint32_t translated;
        size_t l;
        int r;

        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

        assert(name);
        assert(pwd);

        /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */
        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                goto not_found;

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_call_method(bus,
                               "org.freedesktop.systemd1",
                               "/org/freedesktop/systemd1",
                               "org.freedesktop.systemd1.Manager",
                               "LookupDynamicUserByName",
                               &error,
                               &reply,
                               "s",
                               name);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER))
                        goto not_found;

                goto fail;
        }

        r = sd_bus_message_read(reply, "u", &translated);
        if (r < 0)
                goto fail;

        l = strlen(name);
        if (buflen < l+1) {
                *errnop = ENOMEM;
                return NSS_STATUS_TRYAGAIN;
        }

        memcpy(buffer, name, l+1);

        pwd->pw_name = buffer;
        pwd->pw_uid = (uid_t) translated;
        pwd->pw_gid = (uid_t) translated;
        pwd->pw_gecos = (char*) "Dynamic User";
        pwd->pw_passwd = (char*) "*"; /* locked */
        pwd->pw_dir = (char*) "/";
        pwd->pw_shell = (char*) "/sbin/nologin";

        *errnop = 0;
        return NSS_STATUS_SUCCESS;

not_found:
        *errnop = 0;
        return NSS_STATUS_NOTFOUND;

fail:
        *errnop = -r;
        return NSS_STATUS_UNAVAIL;
}
Ejemplo n.º 19
0
int bus_verify_polkit(
                sd_bus_message *call,
                int capability,
                const char *action,
                bool interactive,
                bool *_challenge,
                sd_bus_error *e) {

        int r;

        assert(call);
        assert(action);

        r = sd_bus_query_sender_privilege(call, capability);
        if (r < 0)
                return r;
        else if (r > 0)
                return 1;
#ifdef ENABLE_POLKIT
        else {
                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
                int authorized = false, challenge = false;
                const char *sender;

                sender = sd_bus_message_get_sender(call);
                if (!sender)
                        return -EBADMSG;

                r = sd_bus_call_method(
                                call->bus,
                                "org.freedesktop.PolicyKit1",
                                "/org/freedesktop/PolicyKit1/Authority",
                                "org.freedesktop.PolicyKit1.Authority",
                                "CheckAuthorization",
                                e,
                                &reply,
                                "(sa{sv})sa{ss}us",
                                "system-bus-name", 1, "name", "s", sender,
                                action,
                                0,
                                interactive ? 1 : 0,
                                "");

                if (r < 0) {
                        /* Treat no PK available as access denied */
                        if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
                                sd_bus_error_free(e);
                                return -EACCES;
                        }

                        return r;
                }

                r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
                if (r < 0)
                        return r;

                r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
                if (r < 0)
                        return r;

                if (authorized)
                        return 1;

                if (_challenge) {
                        *_challenge = challenge;
                        return 0;
                }
        }
#endif

        return -EACCES;
}
Ejemplo n.º 20
0
static void test_error(void) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL, second = SD_BUS_ERROR_NULL;
        const sd_bus_error const_error = SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_FILE_EXISTS, "const error");
        const sd_bus_error temporarily_const_error = {
                .name = SD_BUS_ERROR_ACCESS_DENIED,
                .message = "oh! no",
                ._need_free = -1
        };

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set(&error, SD_BUS_ERROR_NOT_SUPPORTED, "xxx") == -EOPNOTSUPP);
        assert_se(streq(error.name, SD_BUS_ERROR_NOT_SUPPORTED));
        assert_se(streq(error.message, "xxx"));
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_NOT_SUPPORTED));
        assert_se(sd_bus_error_get_errno(&error) == EOPNOTSUPP);
        assert_se(sd_bus_error_is_set(&error));
        sd_bus_error_free(&error);

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_setf(&error, SD_BUS_ERROR_FILE_NOT_FOUND, "yyy %i", -1) == -ENOENT);
        assert_se(streq(error.name, SD_BUS_ERROR_FILE_NOT_FOUND));
        assert_se(streq(error.message, "yyy -1"));
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_FILE_NOT_FOUND));
        assert_se(sd_bus_error_get_errno(&error) == ENOENT);
        assert_se(sd_bus_error_is_set(&error));

        assert_se(!sd_bus_error_is_set(&second));
        assert_se(second._need_free == 0);
        assert_se(error._need_free > 0);
        assert_se(sd_bus_error_copy(&second, &error) == -ENOENT);
        assert_se(second._need_free > 0);
        assert_se(streq(error.name, second.name));
        assert_se(streq(error.message, second.message));
        assert_se(sd_bus_error_get_errno(&second) == ENOENT);
        assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_NOT_FOUND));
        assert_se(sd_bus_error_is_set(&second));

        sd_bus_error_free(&error);
        sd_bus_error_free(&second);

        assert_se(!sd_bus_error_is_set(&second));
        assert_se(const_error._need_free == 0);
        assert_se(sd_bus_error_copy(&second, &const_error) == -EEXIST);
        assert_se(second._need_free == 0);
        assert_se(streq(const_error.name, second.name));
        assert_se(streq(const_error.message, second.message));
        assert_se(sd_bus_error_get_errno(&second) == EEXIST);
        assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_FILE_EXISTS));
        assert_se(sd_bus_error_is_set(&second));
        sd_bus_error_free(&second);

        assert_se(!sd_bus_error_is_set(&second));
        assert_se(temporarily_const_error._need_free < 0);
        assert_se(sd_bus_error_copy(&second, &temporarily_const_error) == -EACCES);
        assert_se(second._need_free > 0);
        assert_se(streq(temporarily_const_error.name, second.name));
        assert_se(streq(temporarily_const_error.message, second.message));
        assert_se(sd_bus_error_get_errno(&second) == EACCES);
        assert_se(sd_bus_error_has_name(&second, SD_BUS_ERROR_ACCESS_DENIED));
        assert_se(sd_bus_error_is_set(&second));

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set_const(&error, "System.Error.EUCLEAN", "Hallo") == -EUCLEAN);
        assert_se(streq(error.name, "System.Error.EUCLEAN"));
        assert_se(streq(error.message, "Hallo"));
        assert_se(sd_bus_error_has_name(&error, "System.Error.EUCLEAN"));
        assert_se(sd_bus_error_get_errno(&error) == EUCLEAN);
        assert_se(sd_bus_error_is_set(&error));
        sd_bus_error_free(&error);

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set_errno(&error, EBUSY) == -EBUSY);
        assert_se(streq(error.name, "System.Error.EBUSY"));
        assert_se(streq(error.message, strerror(EBUSY)));
        assert_se(sd_bus_error_has_name(&error, "System.Error.EBUSY"));
        assert_se(sd_bus_error_get_errno(&error) == EBUSY);
        assert_se(sd_bus_error_is_set(&error));
        sd_bus_error_free(&error);

        assert_se(!sd_bus_error_is_set(&error));
        assert_se(sd_bus_error_set_errnof(&error, EIO, "Waldi %c", 'X') == -EIO);
        assert_se(streq(error.name, SD_BUS_ERROR_IO_ERROR));
        assert_se(streq(error.message, "Waldi X"));
        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_IO_ERROR));
        assert_se(sd_bus_error_get_errno(&error) == EIO);
        assert_se(sd_bus_error_is_set(&error));
}

extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];

static void dump_mapping_table(void) {
        const sd_bus_error_map *m;

        printf("----- errno mappings ------\n");
        m = __start_BUS_ERROR_MAP;
        while (m < __stop_BUS_ERROR_MAP) {

                if (m->code == BUS_ERROR_MAP_END_MARKER) {
                        m = ALIGN8_PTR(m+1);
                        continue;
                }

                printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code)));
                m ++;
        }
        printf("---------------------------\n");
}

static void test_errno_mapping_standard(void) {
        assert_se(sd_bus_error_set(NULL, "System.Error.EUCLEAN", NULL) == -EUCLEAN);
        assert_se(sd_bus_error_set(NULL, "System.Error.EBUSY", NULL) == -EBUSY);
        assert_se(sd_bus_error_set(NULL, "System.Error.EINVAL", NULL) == -EINVAL);
        assert_se(sd_bus_error_set(NULL, "System.Error.WHATSIT", NULL) == -EIO);
}
Ejemplo n.º 21
0
enum nss_status _nss_resolve_gethostbyname4_r(
                const char *name,
                struct gaih_addrtuple **pat,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        enum nss_status ret = NSS_STATUS_UNAVAIL;
        const char *canonical = NULL;
        size_t l, ms, idx;
        char *r_name;
        int c, r, i = 0;

        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

        assert(name);
        assert(pat);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
                        *errnop = ESRCH;
                        *h_errnop = HOST_NOT_FOUND;
                        return NSS_STATUS_NOTFOUND;
                }

                /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails,
                   allowing falling back to other nss modules. Treat all other error conditions as
                   NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this
                   case so that the nsswitch.conf configuration can distuingish such executed but
                   negative replies from complete failure to talk to resolved). */
                if (!bus_error_shall_fallback(&error))
                        ret = NSS_STATUS_NOTFOUND;

                goto fail;
        }

        c = count_addresses(reply, AF_UNSPEC, &canonical);
        if (c < 0) {
                r = c;
                goto fail;
        }
        if (c == 0) {
                *errnop = ESRCH;
                *h_errnop = HOST_NOT_FOUND;
                return NSS_STATUS_NOTFOUND;
        }

        if (isempty(canonical))
                canonical = name;

        l = strlen(canonical);
        ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
        if (buflen < ms) {
                *errnop = ERANGE;
                *h_errnop = NETDB_INTERNAL;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, append name */
        r_name = buffer;
        memcpy(r_name, canonical, l+1);
        idx = ALIGN(l+1);

        /* Second, append addresses */
        r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                int family, ifindex;
                const void *a;
                size_t sz;

                assert_cc(sizeof(int32_t) == sizeof(int));

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        goto fail;

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        goto fail;

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        goto fail;

                if (!IN_SET(family, AF_INET, AF_INET6))
                        continue;

                if (sz != FAMILY_ADDRESS_SIZE(family)) {
                        r = -EINVAL;
                        goto fail;
                }

                r_tuple = (struct gaih_addrtuple*) (buffer + idx);
                r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
                r_tuple->name = r_name;
                r_tuple->family = family;
                r_tuple->scopeid = ifindex_to_scopeid(family, a, ifindex);
                memcpy(r_tuple->addr, a, sz);

                idx += ALIGN(sizeof(struct gaih_addrtuple));
                i++;
        }
        if (r < 0)
                goto fail;

        assert(i == c);
        assert(idx == ms);

        if (*pat)
                **pat = *r_tuple_first;
        else
                *pat = r_tuple_first;

        if (ttlp)
                *ttlp = 0;

        /* Explicitly reset all error variables */
        *errnop = 0;
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_RECOVERY;
        return ret;
}
Ejemplo n.º 22
0
enum nss_status _nss_resolve_gethostbyname3_r(
                const char *name,
                int af,
                struct hostent *result,
                char *buffer, size_t buflen,
                int *errnop, int *h_errnop,
                int32_t *ttlp,
                char **canonp) {

        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        char *r_name, *r_aliases, *r_addr, *r_addr_list;
        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
        enum nss_status ret = NSS_STATUS_UNAVAIL;
        size_t l, idx, ms, alen;
        const char *canonical;
        int c, r, i = 0;

        PROTECT_ERRNO;
        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);

        assert(name);
        assert(result);
        assert(buffer);
        assert(errnop);
        assert(h_errnop);

        if (af == AF_UNSPEC)
                af = AF_INET;

        if (!IN_SET(af, AF_INET, AF_INET6)) {
                r = -EAFNOSUPPORT;
                goto fail;
        }

        if (avoid_deadlock()) {
                r = -EDEADLK;
                goto fail;
        }

        r = sd_bus_open_system(&bus);
        if (r < 0)
                goto fail;

        r = sd_bus_message_new_method_call(
                        bus,
                        &req,
                        "org.freedesktop.resolve1",
                        "/org/freedesktop/resolve1",
                        "org.freedesktop.resolve1.Manager",
                        "ResolveHostname");
        if (r < 0)
                goto fail;

        r = sd_bus_message_set_auto_start(req, false);
        if (r < 0)
                goto fail;

        r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
        if (r < 0)
                goto fail;

        r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
        if (r < 0) {
                if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN") ||
                    !bus_error_shall_fallback(&error))
                        goto not_found;

                goto fail;
        }

        c = count_addresses(reply, af, &canonical);
        if (c < 0) {
                r = c;
                goto fail;
        }
        if (c == 0)
                goto not_found;

        if (isempty(canonical))
                canonical = name;

        alen = FAMILY_ADDRESS_SIZE(af);
        l = strlen(canonical);

        ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);

        if (buflen < ms) {
                *errnop = ERANGE;
                *h_errnop = NETDB_INTERNAL;
                return NSS_STATUS_TRYAGAIN;
        }

        /* First, append name */
        r_name = buffer;
        memcpy(r_name, canonical, l+1);
        idx = ALIGN(l+1);

        /* Second, create empty aliases array */
        r_aliases = buffer + idx;
        ((char**) r_aliases)[0] = NULL;
        idx += sizeof(char*);

        /* Third, append addresses */
        r_addr = buffer + idx;

        r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
        if (r < 0)
                goto fail;

        while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
                int ifindex, family;
                const void *a;
                size_t sz;

                r = sd_bus_message_read(reply, "ii", &ifindex, &family);
                if (r < 0)
                        goto fail;

                if (ifindex < 0) {
                        r = -EINVAL;
                        goto fail;
                }

                r = sd_bus_message_read_array(reply, 'y', &a, &sz);
                if (r < 0)
                        goto fail;

                r = sd_bus_message_exit_container(reply);
                if (r < 0)
                        goto fail;

                if (family != af)
                        continue;

                if (sz != alen) {
                        r = -EINVAL;
                        goto fail;
                }

                memcpy(r_addr + i*ALIGN(alen), a, alen);
                i++;
        }
        if (r < 0)
                goto fail;

        assert(i == c);
        idx += c * ALIGN(alen);

        /* Fourth, append address pointer array */
        r_addr_list = buffer + idx;
        for (i = 0; i < c; i++)
                ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);

        ((char**) r_addr_list)[i] = NULL;
        idx += (c+1) * sizeof(char*);

        assert(idx == ms);

        result->h_name = r_name;
        result->h_aliases = (char**) r_aliases;
        result->h_addrtype = af;
        result->h_length = alen;
        result->h_addr_list = (char**) r_addr_list;

        if (ttlp)
                *ttlp = 0;

        if (canonp)
                *canonp = r_name;

        /* Explicitly reset both *h_errnop and h_errno to work around
         * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */
        *h_errnop = NETDB_SUCCESS;
        h_errno = 0;

        return NSS_STATUS_SUCCESS;

fail:
        *errnop = -r;
        *h_errnop = NO_RECOVERY;
        return ret;

not_found:
        *h_errnop = HOST_NOT_FOUND;
        return NSS_STATUS_NOTFOUND;
}