chiark / gitweb /
bus: when replying to an incoming message and the vtable contains the expected return...
authorLennart Poettering <lennart@poettering.net>
Mon, 2 Dec 2013 14:28:20 +0000 (15:28 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 2 Dec 2013 14:29:40 +0000 (15:29 +0100)
TODO
src/libsystemd-bus/bus-message.c
src/libsystemd-bus/bus-message.h
src/libsystemd-bus/bus-objects.c
src/libsystemd-bus/test-bus-objects.c

diff --git a/TODO b/TODO
index cfabfca9f9f3cf456797dae808bbd2f55798133d..d2e5348ba845a0bf531bdb180769890dbdefae4d 100644 (file)
--- a/TODO
+++ b/TODO
@@ -124,7 +124,6 @@ Features:
   - implement monitor logic
   - properly map matches with well-known names against messages with unique names
   - when triggering property change events, allow a NULL strv indicate that all properties listed as such are send out as changed
-  - enforce signatures on response messages
   - see if we can drop more message validation on the sending side
   - support "const" properties as flag
   - add API to clone sd_bus_message objects
index a1e6c9f97368123fd9143c71a4e31853566d092c..dc856944719c50406f5419a96e0e1875714a0d86 100644 (file)
@@ -568,6 +568,7 @@ static int message_new_reply(
         }
 
         t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED);
+        t->enforced_reply_signature = call->enforced_reply_signature;
 
         *m = t;
         return 0;
@@ -3962,6 +3963,13 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) {
         if (m->poisoned)
                 return -ESTALE;
 
+        /* In vtables the return signature of method calls is listed,
+         * let's check if they match if this is a response */
+        if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN &&
+            m->enforced_reply_signature &&
+            !streq(strempty(m->root_container.signature), m->enforced_reply_signature))
+                return -ENOMSG;
+
         /* If there's a non-trivial signature set, then add it in here */
         if (!isempty(m->root_container.signature)) {
                 r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
index 72a79f792b4276b568e316187f5f750cf4151785..34dbc5d563430310fa39204b47d56de5b8cf1928 100644 (file)
@@ -116,6 +116,11 @@ struct sd_bus_message {
 
         char *peeked_signature;
 
+        /* If set replies to this message must carry the signature
+         * specified here to successfully seal. This is initialized
+         * from the vtable data */
+        const char *enforced_reply_signature;
+
         usec_t timeout;
 
         char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1];
index 05a62f4a3ec6eb61883332af53b5aa25a636230e..7cd34c991b004f389c06656e37d1e9eca20fb251 100644 (file)
@@ -312,6 +312,11 @@ static int method_callbacks_run(
                                 "Invalid arguments '%s' to call %s.%s(), expecting '%s'.",
                                 signature, c->interface, c->member, strempty(c->vtable->x.method.signature));
 
+        /* Keep track what the signature of the reply to this message
+         * should be, so that this can be enforced when sealing the
+         * reply. */
+        m->enforced_reply_signature = strempty(c->vtable->x.method.result);
+
         if (c->vtable->x.method.handler) {
                 r = c->vtable->x.method.handler(bus, m, u, &error);
                 return bus_maybe_reply_error(m, r, &error);
index 95278e36e3ee56ff9b69c7fd767a5ed80dc11541..0ab7a148d30d2f48e6d97756161410ae01c857d3 100644 (file)
@@ -61,6 +61,9 @@ static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_
 
         log_info("AlterSomething() called, got %s, returning %s", s, n);
 
+        /* This should fail, since the return type doesn't match */
+        assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG);
+
         r = sd_bus_reply_method_return(m, "s", n);
         assert_se(r >= 0);