d9577dbd92555b0755881e37724019ef9c578404Stef Walter Stef Walter <stefw@redhat.com>
d9577dbd92555b0755881e37724019ef9c578404Stef Walter Copyright (C) 2014 Red Hat
d9577dbd92555b0755881e37724019ef9c578404Stef Walter This program is free software; you can redistribute it and/or modify
d9577dbd92555b0755881e37724019ef9c578404Stef Walter it under the terms of the GNU General Public License as published by
d9577dbd92555b0755881e37724019ef9c578404Stef Walter the Free Software Foundation; either version 3 of the License, or
d9577dbd92555b0755881e37724019ef9c578404Stef Walter (at your option) any later version.
d9577dbd92555b0755881e37724019ef9c578404Stef Walter This program is distributed in the hope that it will be useful,
d9577dbd92555b0755881e37724019ef9c578404Stef Walter but WITHOUT ANY WARRANTY; without even the implied warranty of
d9577dbd92555b0755881e37724019ef9c578404Stef Walter MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d9577dbd92555b0755881e37724019ef9c578404Stef Walter GNU General Public License for more details.
d9577dbd92555b0755881e37724019ef9c578404Stef Walter You should have received a copy of the GNU General Public License
d9577dbd92555b0755881e37724019ef9c578404Stef Walter along with this program. If not, see <http://www.gnu.org/licenses/>.
d9577dbd92555b0755881e37724019ef9c578404Stef Walterstatic int sbus_request_destructor(struct sbus_request *dbus_req)
d9577dbd92555b0755881e37724019ef9c578404Stef Walter dbus_req = talloc_zero(conn, struct sbus_request);
d9577dbd92555b0755881e37724019ef9c578404Stef Walter DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory allocating DBus request\n");
71c9027d4192bf149afa4fcf9fef93bf6e901121Pavel Březina dbus_req->path = dbus_message_get_path(message);
d9577dbd92555b0755881e37724019ef9c578404Stef Walter talloc_set_destructor(dbus_req, sbus_request_destructor);
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Waltersbus_request_invoke_or_finish(struct sbus_request *dbus_req,
dff909d473f43a6bd0f0286fa2d279c0ebe945c6Stef Walter DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory handling DBus message\n");
91c637615fc45679235b3371792e2eaf63a62b4fPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Handler failed [%d]: %s\n",
8779b9ee101ed3e5a6836b5366c006dc21dd36c0Pavel Březina dbus_set_error_const(&error, DBUS_ERROR_FAILED, INTERNAL_ERROR);
8779b9ee101ed3e5a6836b5366c006dc21dd36c0Pavel Březina sbus_request_fail_and_finish(dbus_req, &error);
d9577dbd92555b0755881e37724019ef9c578404Stef Walterint sbus_request_finish(struct sbus_request *dbus_req,
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozekstatic int sbus_request_valist_check(va_list va, int first_arg_type)
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek value = va_arg(va_check, const DBusBasicValue*);
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek ok = sss_utf8_check((const uint8_t *) value->str,
de1131abe5ba7aaeb59f81fc3a9cd2a71c0b52ddLukas Slebodnik "sbus message argument [%s] contains invalid "
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek#endif /* HAVE_DBUSBASICVALUE */
d9577dbd92555b0755881e37724019ef9c578404Stef Walterint sbus_request_return_and_finish(struct sbus_request *dbus_req,
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek ret = sbus_request_valist_check(va, first_arg_type);
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek dbus_set_error_const(&error, DBUS_ERROR_INVALID_ARGS, INTERNAL_ERROR);
6b01dae732eedee808f32a9cdd4b5656a9f839c4Jakub Hrozek return sbus_request_fail_and_finish(dbus_req, &error);
d9577dbd92555b0755881e37724019ef9c578404Stef Walter reply = dbus_message_new_method_return(dbus_req->message);
d9577dbd92555b0755881e37724019ef9c578404Stef Walter DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory allocating DBus message\n");
d9577dbd92555b0755881e37724019ef9c578404Stef Walter dbret = dbus_message_append_args_valist(reply, first_arg_type, va);
d9577dbd92555b0755881e37724019ef9c578404Stef Walter DEBUG(SSSDBG_CRIT_FAILURE, "Couldn't build DBus message\n");
d9577dbd92555b0755881e37724019ef9c578404Stef Walterint sbus_request_fail_and_finish(struct sbus_request *dbus_req,
d9577dbd92555b0755881e37724019ef9c578404Stef Walter reply = dbus_message_new_error(dbus_req->message, error->name, error->message);
d9577dbd92555b0755881e37724019ef9c578404Stef Walter DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory allocating DBus message\n");
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březinastatic DBusError *sbus_error_new_va(TALLOC_CTX *mem_ctx,
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březina const char *fmt,
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březina dbus_set_error_const(error, error_name, error_msg);
87729e3a6c56383642a8d3a86b2856487f2ee064Jakub Hrozek const char *fmt,
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březina error = sbus_error_new_va(mem_ctx, dbus_error_name, fmt, ap);
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březinavoid sbus_request_reply_error(struct sbus_request *sbus_req,
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březina const char *fmt,
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březina error = sbus_error_new_va(sbus_req, error_name, fmt, ap);
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březina "Unable to create D-Bus error, killing request!\n");
a06e23c0bcf0c8669a29b801876aca8aac422931Pavel Březina sbus_request_fail_and_finish(sbus_req, error);
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walterstatic int array_arg_destructor(struct array_arg *arg)
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walterparent_dbus_string_arrays(struct sbus_request *request, int first_arg_type,
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter * Here we iterate through the entire thing again and look for
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter * things we need to fix allocation for. Normally certain types
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter * returned from dbus_message_get_args() and friends require
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter * later freeing. We tie those to the talloc context here.
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter * The list of argument has already been validated by the previous
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter * dbus_message_get_args() call, so we can be cheap.
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter arg_type = va_arg(va, int); /* the array element type */
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter arg_ptr = va_arg(va, void **); /* the array elements */
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter /* Arrays of these things need to be freed */
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter array_arg = talloc_zero(request, struct array_arg);
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter /* no kidding ... */
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory while trying not to leak memory\n");
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter return false;
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter talloc_set_destructor(array_arg, array_arg_destructor);
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter /* A non array argument */
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter /* The next type */
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter return true;
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Waltersbus_request_parse_or_finish(struct sbus_request *request,
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter if (dbus_message_get_args_valist(request->message, &error,
3d5908ed0faf400a5c7d9c3e4312597ee1b7786aJakub Hrozek ret = parent_dbus_string_arrays(request, first_arg_type, va2);
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter /* Trying to send the error back to the caller in this case is a joke */
94f07a6f4375ec25d8fa5c99a0c4f68de7002457Jakub Hrozek dbus_error_has_name(&error, DBUS_ERROR_NO_MEMORY)) {
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory parsing DBus message\n");
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter /* Log other errors and send them back, this include o.f.d.InvalidArgs */
06b7bc8ca2e005ed510210d3b8dee16afbabbcc9Stef Walter DEBUG(SSSDBG_OP_FAILURE, "Couldn't parse DBus message %s.%s: %s\n",
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozekstatic void sbus_get_sender_id_done(DBusPendingCall *pending, void *ptr);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozekstruct tevent_req *sbus_get_sender_id_send(TALLOC_CTX *mem_ctx,
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek req = tevent_req_create(mem_ctx, &state, struct sbus_get_sender_id_state);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek if (conn->connection_type != SBUS_CONN_TYPE_SYSBUS) {
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "Not a sysbus message, quit\n");
9118a539a5d59f669f551114f880fe91d6bb8741Jakub Hrozek if (strcmp(sender, "org.freedesktop.DBus") == 0) {
6c2a29a912f4c995343315f1f70c825ca2200640Jakub Hrozek "Looking for identity of sender [%s]\n", sender);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek ret = hash_lookup(conn->clients, &key, &value);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek "%s already present in the clients table\n", sender);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek "Failed to look up %s in the clients table\n", sender);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek /* We don't know this sender yet, let's ask the system bus */
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek /* Connect to the well-known system bus */
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek state->sysbus_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek "Failed to connect to D-BUS system bus.\n");
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek dbus_connection_set_exit_on_disconnect(state->sysbus_conn, FALSE);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek /* If we ever need to get the SELinux context or the PID here, we need
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek * to call GetConnectionCredentials instead
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek msg = dbus_message_new_method_call("org.freedesktop.DBus", /* bus name */
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek "GetConnectionUnixUser");
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory?!\n");
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek ret = sss_dbus_conn_send(state->sysbus_conn, msg, 3000,
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozekstatic void sbus_get_sender_id_done(DBusPendingCall *pending, void *ptr)
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek state = tevent_req_data(req, struct sbus_get_sender_id_state);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek reply = dbus_pending_call_steal_reply(pending);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek /* reply should never be null. This function shouldn't be called
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek * until reply is valid or timeout has occurred. If reply is NULL
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek * here, something is seriously wrong and we should bail out.
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek "Severe error. A reply callback was called but no reply "
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek "was received and no timeout occurred\n");
6c2a29a912f4c995343315f1f70c825ca2200640Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Could not parse reply!\n");
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek key.str = talloc_steal(state->conn->clients, state->sender);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek ret = hash_enter(state->conn->clients, &key, &value);
6c2a29a912f4c995343315f1f70c825ca2200640Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Could not add key to hash table!\n");
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozekint sbus_get_sender_id_recv(struct tevent_req *req, int64_t *_uid)