X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-convenience.c;h=ae0f4fa217777cca1450ff60b37b1d70adbd80a7;hp=6e02ad365c844a0fe8176b8c26833a9b2087172d;hb=75e52a16f9ef476f1d18ec6d9c84e00149b80d03;hpb=151b9b9662a90455262ce575a8a8ae74bf4ff336 diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c index 6e02ad365..ae0f4fa21 100644 --- a/src/libsystemd/sd-bus/bus-convenience.c +++ b/src/libsystemd/sd-bus/bus-convenience.c @@ -36,9 +36,11 @@ _public_ int sd_bus_emit_signal( int r; assert_return(bus, -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + r = sd_bus_message_new_signal(bus, &m, path, interface, member); if (r < 0) return r; @@ -70,9 +72,11 @@ _public_ int sd_bus_call_method( int r; assert_return(bus, -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member); if (r < 0) return r; @@ -100,9 +104,12 @@ _public_ int sd_bus_reply_method_return( assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); - assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN); + assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; @@ -134,9 +141,12 @@ _public_ int sd_bus_reply_method_error( assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(sd_bus_error_is_set(e), -EINVAL); - assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN); + assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; @@ -159,9 +169,12 @@ _public_ int sd_bus_reply_method_errorf( assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); - assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN); + assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; @@ -182,9 +195,12 @@ _public_ int sd_bus_reply_method_errno( assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); - assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN); + assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; @@ -208,9 +224,12 @@ _public_ int sd_bus_reply_method_errnof( assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); - assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN); + assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; @@ -239,9 +258,11 @@ _public_ int sd_bus_get_property( assert_return(member_name_is_valid(member), -EINVAL); assert_return(reply, -EINVAL); assert_return(signature_is_single(type, false), -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member); if (r < 0) return r; @@ -273,9 +294,11 @@ _public_ int sd_bus_get_property_trivial( assert_return(member_name_is_valid(member), -EINVAL); assert_return(bus_type_is_trivial(type), -EINVAL); assert_return(ptr, -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) return r; @@ -309,9 +332,11 @@ _public_ int sd_bus_get_property_string( assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); assert_return(member_name_is_valid(member), -EINVAL); assert_return(ret, -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) return r; @@ -348,9 +373,11 @@ _public_ int sd_bus_get_property_strv( assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); assert_return(member_name_is_valid(member), -EINVAL); assert_return(ret, -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member); if (r < 0) return r; @@ -383,9 +410,11 @@ _public_ int sd_bus_set_property( assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL); assert_return(member_name_is_valid(member), -EINVAL); assert_return(signature_is_single(type, false), -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); + if (!BUS_IS_OPEN(bus->state)) + return -ENOTCONN; + r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set"); if (r < 0) return r; @@ -416,9 +445,12 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); - assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN); + assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + c = sd_bus_message_get_creds(call); /* All data we need? */ @@ -433,10 +465,68 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b * to get it from the sender or peer */ if (call->sender) - return sd_bus_get_owner(call->bus, call->sender, mask, creds); + return sd_bus_get_name_creds(call->bus, call->sender, mask, creds); else - return sd_bus_get_peer_creds(call->bus, mask, creds); + return sd_bus_get_owner_creds(call->bus, mask, creds); } return bus_creds_extend_by_pid(c, mask, creds); } + +_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) { + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + uid_t our_uid; + bool know_caps = false; + int r; + + assert_return(call, -EINVAL); + assert_return(call->sealed, -EPERM); + assert_return(call->bus, -EINVAL); + assert_return(!bus_pid_changed(call->bus), -ECHILD); + + if (!BUS_IS_OPEN(call->bus->state)) + return -ENOTCONN; + + if (capability >= 0) { + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); + if (r < 0) + return r; + + /* Note that not even on kdbus we might have the caps + * field, due to faked identities, or namespace + * translation issues. */ + r = sd_bus_creds_has_effective_cap(creds, capability); + if (r > 0) + return 1; + if (r == 0) + know_caps = true; + } else { + r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + } + + /* Now, check the UID, but only if the capability check wasn't + * sufficient */ + our_uid = getuid(); + if (our_uid != 0 || !know_caps || capability < 0) { + uid_t sender_uid; + + /* Try to use the EUID, if we have it. */ + r = sd_bus_creds_get_euid(creds, &sender_uid); + if (r < 0) + r = sd_bus_creds_get_uid(creds, &sender_uid); + + if (r >= 0) { + /* Sender has same UID as us, then let's grant access */ + if (sender_uid == our_uid) + return 1; + + /* Sender is root, we are not root. */ + if (our_uid != 0 && sender_uid == 0) + return 1; + } + } + + return 0; +}