responder_dp.c revision d3f2fd9cb21cc10dce663a2f7d0deda07074e44e
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen Simo Sorce <ssorce@redhat.com>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen Stephen Gallagher <sgallagh@redhat.com>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen Copyright (C) 2009 Red Hat
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen This program is free software; you can redistribute it and/or modify
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen it under the terms of the GNU General Public License as published by
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen the Free Software Foundation; either version 3 of the License, or
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (at your option) any later version.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen This program is distributed in the hope that it will be useful,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen GNU General Public License for more details.
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen You should have received a copy of the GNU General Public License
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int sss_dp_callback_destructor(void *ptr)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct sss_dp_req *sdp_req = talloc_get_type(ptr, struct sss_dp_req);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* Cancel Dbus pending reply if still pending */
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen dbus_pending_call_cancel(sdp_req->pending_reply);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* If there are callbacks that haven't been invoked, return
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen * an error now.
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen state = tevent_req_data(cb->req, struct sss_dp_req_state);
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen /* tevent_req_done/error will free cb */
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen /* Freeing the cb removes it from the cb_list.
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen * Therefore, the cb_list should now be pointing
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen * at a new callback. If it's not, it means the
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen * callback handler didn't free cb and may leak
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen * memory. Be paranoid and protect against this
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen ("BUG: a callback did not free its request. "
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen "May leak memory\n"));
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen /* Skip to the next since a memory leak is non-fatal */
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* Destroy the hash entry */
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, ("Deleting request: [%s]\n", sdp_req->key->str));
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen hret = hash_delete(sdp_req->rctx->dp_request_table, sdp_req->key);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* This should never happen */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ("BUG: Could not clear [%d:%d:%s] from request queue: [%s]\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sdp_req->key->type, sdp_req->key->ul, sdp_req->key->str,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid handle_requests_after_reconnect(struct resp_ctx *rctx)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned long count, i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(7, ("No requests to handle after reconnect\n"));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = hash_values(rctx->dp_request_table, &count, &values);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "not all request might be handled after reconnect.\n"));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(7, ("Will handle %lu requests after reconnect\n", count));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i=0; i<count; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sdp_req = talloc_get_type(values[i].ptr, struct sss_dp_req);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int sss_dp_get_reply(DBusPendingCall *pending,
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen reply = dbus_pending_call_steal_reply(pending);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* reply should never be null. This function shouldn't be called
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen * until reply is valid or timeout has occurred. If reply is NULL
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen * here, something is seriously wrong and we should bail out.
d74c7c6d900f7b38017403a0da9106b8a6c647b2Timo Sirainen ("Severe error. A reply callback was called but no reply "
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen "was received and no timeout occurred\n"));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* FIXME: Destroy this connection ? */
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen ret = dbus_message_get_args(reply, &dbus_error,
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen /* FIXME: Destroy this connection ? */
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen ("Got reply from Data Provider - "
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen "DP error code: %u errno: %u error message: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (strcmp(dbus_message_get_error_name(reply),
d74c7c6d900f7b38017403a0da9106b8a6c647b2Timo Sirainen DEBUG(0,("The Data Provider returned an error [%s]\n",
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen /* Falling through to default intentionally*/
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen * Timeout or other error occurred or something
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * unexpected happened.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * It doesn't matter which, because either way we
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * know that this connection isn't trustworthy.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * We'll destroy it now.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* FIXME: Destroy this connection ? */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic struct tevent_req *
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainensss_dp_internal_get_send(struct resp_ctx *rctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainensss_dp_issue_request(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *strkey, struct sss_domain_info *dom,
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen key->str = talloc_asprintf(key, "%p:%s", msg_create, strkey);
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, ("Issuing request for [%s]\n", key->str));
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen /* Check the hash for existing references to this request */
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen hret = hash_lookup(rctx->dp_request_table, key, &value);
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen /* Request already in progress */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen ("Identical request in progress: [%s]\n", key->str));
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* No such request in progress
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen * Create a new request
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot create D-Bus message\n"));
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen sidereq = sss_dp_internal_get_send(rctx, key, dom, msg);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot send D-Bus message\n"));
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen tevent_req_set_callback(sidereq, sss_dp_req_done, NULL);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* We should now be able to find the sdp_req in the hash table */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen hret = hash_lookup(rctx->dp_request_table, key, &value);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* Something must have gone wrong with creating the request */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, ("The request has disappeared?\n"));
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen ("Could not query request list (%s)\n",
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* Register this request for results */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen sdp_req = talloc_get_type(value.ptr, struct sss_dp_req);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, ("Could not retrieve DP request context\n"));
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen cb = talloc_zero(mem_ctx, struct sss_dp_callback);
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen /* Add it to the list of requests to call */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Nothing to do here. The callbacks have already been invoked */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen tevent_req_data(sidereq, struct sss_dp_req_state);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *err_msg = talloc_steal(mem_ctx, state->err_msg);
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen if (tevent_req_is_error(sidereq, &TRROEstate, &TRROEerr)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Send a request to the data provider
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen * Once this function is called, the communication
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * with the data provider will always run to
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * completion. Freeing the returned tevent_req will
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * cancel the notification of completion, but not
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * the data provider action.
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainenstatic DBusMessage *sss_dp_get_account_msg(void *pvt);
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen req = tevent_req_create(mem_ctx, &state, struct sss_dp_req_state);
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen /* either, or, not both */
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen info = talloc_zero(state, struct sss_dp_account_info);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen } else if (opt_id) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen key = talloc_asprintf(state, "%d:%d@%s", type, opt_id, dom->name);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen key = talloc_asprintf(state, "%d:*@%s", type, dom->name);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen ret = sss_dp_issue_request(state, rctx, key, dom, sss_dp_get_account_msg,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ("Could not issue DP request [%d]: %s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen info = talloc_get_type(pvt, struct sss_dp_account_info);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen filter = talloc_asprintf(info, "name=%s", info->opt_name);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen filter = talloc_asprintf(info, "idnumber=%u:%s",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen filter = talloc_asprintf(info, "idnumber=%u", info->opt_id);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory?!\n"));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory?!\n"));
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen /* create the message */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ("Creating request for [%s][%u][%d][%s]\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to build message\n"));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return sss_dp_req_recv(mem_ctx, req, dp_err, dp_ret, err_msg);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void sss_dp_internal_get_done(DBusPendingCall *pending, void *ptr);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic struct tevent_req *
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainensss_dp_internal_get_send(struct resp_ctx *rctx,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Internal requests need to be allocated on the responder context
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * so that they don't go away if a client disconnects. The worst-
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * case scenario here is that the cache is updated without any
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * client expecting a response.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen state->sdp_req = talloc_zero(state, struct sss_dp_req);
a3dcda4b01461c7690c655a013ec12851cdb78d4Timo Sirainen /* Copy the key to use when calling the destructor
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * It needs to be a copy because the original request
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * might be freed if it no longer cares about the reply.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen state->sdp_req->key = talloc_steal(state->sdp_req, key);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* double check dp_ctx has actually been initialized.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * in some pathological cases it may happen that nss starts up before
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * dp connection code is actually able to establish a connection.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = sss_dp_get_domain_conn(rctx, dom->conn_name, &be_conn);
5fc02738b38ac2b0c21db0854d7a5ad452b1177fTimo Sirainen ("BUG: The Data Provider connection for %s is not available!",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * Critical Failure
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * We can't communicate on this connection
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ("D-BUS send failed.\n"));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Add this sdp_req to the hash table */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen DEBUG(SSSDBG_TRACE_FUNC, ("Entering request [%s]\n", key->str));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen hret = hash_enter(rctx->dp_request_table, key, &value);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ("Could not store request query (%s)\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen talloc_set_destructor((TALLOC_CTX *)state->sdp_req,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void sss_dp_internal_get_done(DBusPendingCall *pending, void *ptr)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen req = talloc_get_type(ptr, struct tevent_req);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen state = tevent_req_data(req, struct dp_internal_get_state);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* prevent trying to cancel a reply that we already received */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sdp_req->err_msg = talloc_strdup(sdp_req, "Request timed out");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Failed to get reply from Data Provider");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Check whether we need to issue any callbacks */
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen cb_state = tevent_req_data(cb->req, struct sss_dp_req_state);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen cb_state->err_msg = talloc_strdup(cb_state, sdp_req->err_msg);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Don't bother checking for NULL. If it fails due to ENOMEM,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen * we can't really handle it anyway.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* tevent_req_done/error will free cb */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* Freeing the cb removes it from the cb_list.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * Therefore, the cb_list should now be pointing
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * at a new callback. If it's not, it means the
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen * callback handler didn't free cb and may leak
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen * memory. Be paranoid and protect against this
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ("BUG: a callback did not free its request. "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "May leak memory\n"));