diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2014-05-09 20:03:31 +0200 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-05-13 21:46:51 +0200 |
commit | 07976be2a09ebb1346c841d4a32e417a8bb43862 (patch) | |
tree | 6db7b40c8a9df7e5723199ac788fca5303fb2a26 /src/sbus | |
parent | 0161a3c5637a0c0092bf54c436bb3d6508d7df26 (diff) | |
download | sssd-07976be2a09ebb1346c841d4a32e417a8bb43862.tar.gz sssd-07976be2a09ebb1346c841d4a32e417a8bb43862.tar.xz sssd-07976be2a09ebb1346c841d4a32e417a8bb43862.zip |
SBUS: Refactor sbus_message_handler to retrieve caller ID
sbus_message_handler() is refactored so that it only verifies the
message matches any of the interfaces SSSD listens on in order to be
able to return either of HANDLED or NOT_YET_HANDLED.
If the interface is one of those the SSSD should handle, the caller ID
is first resolved using sbus_get_sender_id_send and only then passed on
to the appropriate special handler.
If the sernder ID can't be retrieved, the message is dropped with an
error.
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Reviewed-by: Stef Walter <stefw@redhat.com>
Diffstat (limited to 'src/sbus')
-rw-r--r-- | src/sbus/sssd_dbus_connection.c | 166 |
1 files changed, 111 insertions, 55 deletions
diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c index 288fa1f49..618ca63d0 100644 --- a/src/sbus/sssd_dbus_connection.c +++ b/src/sbus/sssd_dbus_connection.c @@ -359,25 +359,22 @@ void sbus_disconnect(struct sbus_connection *conn) #define VTABLE_FUNC(vtable, offset) \ (*((void **)((char *)(vtable) + (offset)))) +static void sbus_handler_got_caller_id(struct tevent_req *req); + /* messsage_handler * Receive messages and process them */ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn, - DBusMessage *message, - void *user_data) + DBusMessage *message, + void *user_data) { struct sbus_interface_p *intf_p; const char *msg_method; const char *path; const char *msg_interface; - DBusMessage *reply = NULL; - const struct sbus_method_meta *method; - const struct sbus_interface_meta *interface; + const char *sender; struct sbus_request *dbus_req = NULL; - sbus_msg_handler_fn handler_fn = NULL; - void *handler_data = NULL; /* Must be a talloc pointer! */ - struct sbus_introspect_ctx *ictx = NULL; - DBusHandlerResult result; + struct tevent_req *req; if (!user_data) { return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -388,40 +385,95 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn, DEBUG(SSSDBG_TRACE_ALL, "Received SBUS method [%s]\n", msg_method); path = dbus_message_get_path(message); msg_interface = dbus_message_get_interface(message); + sender = dbus_message_get_sender(message); - if (!msg_method || !path || !msg_interface) + if (!msg_method || !path || !msg_interface) { return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } /* Validate the D-BUS path */ - if (strcmp(path, intf_p->intf->path) != 0) + if (strcmp(path, intf_p->intf->path) != 0) { return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } /* Validate the method interface */ - interface = intf_p->intf->vtable->meta; + if (strcmp(msg_interface, intf_p->intf->vtable->meta->name) == 0 || + (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 && + strcmp(msg_method, DBUS_INTROSPECT_METHOD) == 0)) { + + /* OK, this message for us. Get the sender ID if applicable */ + dbus_req = sbus_new_request(intf_p->conn, intf_p->intf, message); + if (dbus_req == NULL) { + return DBUS_HANDLER_RESULT_NEED_MEMORY; + } + + req = sbus_get_sender_id_send(dbus_req, dbus_req->conn->ev, + dbus_req->conn, sender); + if (req == NULL) { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + tevent_req_set_callback(req, sbus_handler_got_caller_id, dbus_req); + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void sbus_handler_got_caller_id(struct tevent_req *req) +{ + struct sbus_request *dbus_req = \ + tevent_req_callback_data(req, + struct sbus_request); + errno_t ret; + DBusError *dberr; + DBusMessage *reply = NULL; + const struct sbus_method_meta *method; + const struct sbus_interface_meta *interface; + const char *msg_method; + const char *path; + const char *msg_interface; + const char *sender; + sbus_msg_handler_fn handler_fn = NULL; + void *handler_data = NULL; /* Must be a talloc pointer! */ + struct sbus_introspect_ctx *ictx = NULL; + const char *dbus_error = NULL; + + ret = sbus_get_sender_id_recv(req, &dbus_req->client); + if (ret != EOK) { + dberr = sbus_error_new(dbus_req, + DBUS_ERROR_FAILED, + "Failed to retrieve called ID: %s\n", + sss_strerror(ret)); + sbus_request_fail_and_finish(dbus_req, dberr); + return; + } + + msg_method = dbus_message_get_member(dbus_req->message); + path = dbus_message_get_path(dbus_req->message); + msg_interface = dbus_message_get_interface(dbus_req->message); + sender = dbus_message_get_sender(dbus_req->message); + DEBUG(SSSDBG_TRACE_ALL, "Received SBUS method [%s]\n", msg_method); + + /* Prepare the handler */ + interface = dbus_req->intf->vtable->meta; if (strcmp(msg_interface, interface->name) == 0) { method = sbus_meta_find_method(interface, msg_method); if (method && method->vtable_offset) - handler_fn = VTABLE_FUNC(intf_p->intf->vtable, method->vtable_offset); + handler_fn = VTABLE_FUNC(dbus_req->intf->vtable, + method->vtable_offset); if (!method) { /* Reply DBUS_ERROR_UNKNOWN_METHOD */ DEBUG(SSSDBG_CRIT_FAILURE, "No matching method found for %s.\n", msg_method); - reply = dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD, NULL); - sbus_conn_send_reply(intf_p->conn, reply); - dbus_message_unref(reply); - result = DBUS_HANDLER_RESULT_HANDLED; - + dbus_error = DBUS_ERROR_UNKNOWN_METHOD; + goto fail; } else if (!handler_fn) { /* Reply DBUS_ERROR_NOT_SUPPORTED */ DEBUG(SSSDBG_CRIT_FAILURE, "No handler provided found for %s.\n", msg_method); - reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, NULL); - sbus_conn_send_reply(intf_p->conn, reply); - dbus_message_unref(reply); - result = DBUS_HANDLER_RESULT_HANDLED; + dbus_error = DBUS_ERROR_NOT_SUPPORTED; + goto fail; } } else { /* Special case: check for Introspection request @@ -430,45 +482,49 @@ DBusHandlerResult sbus_message_handler(DBusConnection *dbus_conn, if (strcmp(msg_interface, DBUS_INTROSPECT_INTERFACE) == 0 && strcmp(msg_method, DBUS_INTROSPECT_METHOD) == 0) { DEBUG(SSSDBG_TRACE_LIBS, "Got introspection request\n"); - ictx = talloc(intf_p->conn, struct sbus_introspect_ctx); + ictx = talloc(dbus_req->conn, struct sbus_introspect_ctx); if (ictx == NULL) { - reply = dbus_message_new_error(message, - DBUS_ERROR_NO_MEMORY, NULL); - sbus_conn_send_reply(intf_p->conn, reply); - dbus_message_unref(reply); - result = DBUS_HANDLER_RESULT_HANDLED; - } else { - handler_fn = sbus_introspect; - ictx->iface = interface; - handler_data = ictx; - method = &introspect_method; + dbus_error = DBUS_ERROR_NO_MEMORY; + goto fail; } + + handler_fn = sbus_introspect; + ictx->iface = interface; + handler_data = ictx; + method = &introspect_method; } } - if (handler_fn) { - dbus_req = sbus_new_request(intf_p->conn, intf_p->intf, message); - if (dbus_req) { - dbus_req->method = method; - if (handler_data) { - /* If the handler uses private instance data, make - * sure they go away when the request does - */ - talloc_steal(dbus_req, handler_data); - } else { - /* If no custom handler data is set, pass on the - * interface data - */ - handler_data = intf_p->intf->instance_data; - } + if (handler_fn == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, "No handler matched!\n"); + dbus_error = DBUS_ERROR_NOT_SUPPORTED; + goto fail; + } - sbus_request_invoke_or_finish(dbus_req, handler_fn, handler_data, - method->invoker); - result = DBUS_HANDLER_RESULT_HANDLED; - } + dbus_req->method = method; + if (handler_data) { + /* If the handler uses private instance data, make + * sure they go away when the request does + */ + talloc_steal(dbus_req, handler_data); + } else { + /* If no custom handler data is set, pass on the + * interface data + */ + handler_data = dbus_req->intf->instance_data; } - return result; + sbus_request_invoke_or_finish(dbus_req, + handler_fn, + handler_data, + method->invoker); + return; + +fail: + reply = dbus_message_new_error(dbus_req->message, + dbus_error ? dbus_error : DBUS_ERROR_FAILED, + NULL); + sbus_request_finish(dbus_req, reply); } struct sbus_interface * |