diff options
Diffstat (limited to 'server/nss/nsssrv_dp.c')
-rw-r--r-- | server/nss/nsssrv_dp.c | 432 |
1 files changed, 0 insertions, 432 deletions
diff --git a/server/nss/nsssrv_dp.c b/server/nss/nsssrv_dp.c deleted file mode 100644 index ec8aea8b..00000000 --- a/server/nss/nsssrv_dp.c +++ /dev/null @@ -1,432 +0,0 @@ -/* - SSSD - - NSS Responder - Data Provider Interfaces - - Copyright (C) Simo Sorce <ssorce@redhat.com> 2008 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <sys/time.h> -#include <time.h> -#include "util/util.h" -#include "nss/nsssrv.h" -#include "providers/data_provider.h" -#include "sbus/sbus_client.h" -#include "providers/dp_sbus.h" - -struct nss_dp_req { - nss_dp_callback_t callback; - void *callback_ctx; - struct timed_event *te; - DBusPendingCall *pending_reply; -}; - -static int nss_dp_req_destructor(void *ptr) -{ - struct nss_dp_req *req = talloc_get_type(ptr, struct nss_dp_req); - - if (req->pending_reply) { - dbus_pending_call_cancel(req->pending_reply); - } - - return 0; -} - -static void nss_dp_send_acct_timeout(struct event_context *ev, - struct timed_event *te, - struct timeval t, void *data) -{ - struct nss_dp_req *ndp_req; - dbus_uint16_t err_maj = DP_ERR_TIMEOUT; - dbus_uint32_t err_min = EIO; - const char *err_msg = "Request timed out"; - - ndp_req = talloc_get_type(data, struct nss_dp_req); - - ndp_req->callback(err_maj, err_min, err_msg, ndp_req->callback_ctx); - - talloc_free(ndp_req); -} - -static int nss_dp_get_reply(DBusPendingCall *pending, - dbus_uint16_t *err_maj, - dbus_uint32_t *err_min, - const char **err_msg); - -static void nss_dp_send_acct_callback(DBusPendingCall *pending, void *ptr) -{ - struct nss_dp_req *ndp_req; - dbus_uint16_t err_maj; - dbus_uint32_t err_min; - const char *err_msg; - int ret; - - ndp_req = talloc_get_type(ptr, struct nss_dp_req); - - /* free timeout event and remove request destructor */ - talloc_free(ndp_req->te); - talloc_set_destructor(ndp_req, NULL); - - ret = nss_dp_get_reply(pending, &err_maj, &err_min, &err_msg); - if (ret != EOK) { - err_maj = DP_ERR_FATAL; - err_min = ret; - err_msg = "Failed to get reply from Data Provider"; - } - - ndp_req->callback(err_maj, err_min, err_msg, ndp_req->callback_ctx); - - talloc_free(ndp_req); -} - -int nss_dp_send_acct_req(struct nss_ctx *nctx, TALLOC_CTX *memctx, - nss_dp_callback_t callback, void *callback_ctx, - int timeout, const char *domain, int type, - const char *opt_name, uint32_t opt_id) -{ - struct nss_dp_req *ndp_req; - DBusMessage *msg; - DBusPendingCall *pending_reply; - DBusConnection *conn; - dbus_bool_t ret; - uint32_t be_type; - const char *attrs = "core"; - char *filter; - struct timeval tv; - - /* either, or, not both */ - if (opt_name && opt_id) { - return EINVAL; - } - - if (!domain) { - return EINVAL; - } - - switch (type) { - case NSS_DP_USER: - be_type = BE_REQ_USER; - break; - case NSS_DP_GROUP: - be_type = BE_REQ_GROUP; - break; - case NSS_DP_INITGROUPS: - be_type = BE_REQ_INITGROUPS; - break; - default: - return EINVAL; - } - - if (opt_name) { - filter = talloc_asprintf(memctx, "name=%s", opt_name); - } else if (opt_id) { - filter = talloc_asprintf(memctx, "idnumber=%u", opt_id); - } else { - filter = talloc_strdup(memctx, "name=*"); - } - if (!filter) { - talloc_free(nctx); - return ENOMEM; - } - - conn = sbus_get_connection(nctx->dp_ctx->scon_ctx); - - /* create the message */ - msg = dbus_message_new_method_call(NULL, - DP_CLI_PATH, - DP_CLI_INTERFACE, - DP_SRV_METHOD_GETACCTINFO); - if (msg == NULL) { - DEBUG(0,("Out of memory?!\n")); - return ENOMEM; - } - - DEBUG(4, ("Sending request for [%s][%u][%s][%s]\n", - domain, be_type, attrs, filter)); - - ret = dbus_message_append_args(msg, - DBUS_TYPE_STRING, &domain, - DBUS_TYPE_UINT32, &be_type, - DBUS_TYPE_STRING, &attrs, - DBUS_TYPE_STRING, &filter, - DBUS_TYPE_INVALID); - if (!ret) { - DEBUG(1,("Failed to build message\n")); - return EIO; - } - - ret = dbus_connection_send_with_reply(conn, msg, &pending_reply, - 600000 /* TODO: set timeout */); - if (!ret) { - /* - * Critical Failure - * We can't communicate on this connection - * We'll drop it using the default destructor. - */ - DEBUG(0, ("D-BUS send failed.\n")); - dbus_message_unref(msg); - return EIO; - } - - ndp_req = talloc_zero(memctx, struct nss_dp_req); - if (!ndp_req) { - dbus_message_unref(msg); - return ENOMEM; - } - ndp_req->callback = callback; - ndp_req->callback_ctx = callback_ctx; - - /* set up destructor */ - ndp_req->pending_reply = pending_reply; - talloc_set_destructor((TALLOC_CTX *)ndp_req, nss_dp_req_destructor); - - /* setup the timeout handler */ - gettimeofday(&tv, NULL); - tv.tv_sec += timeout/1000; - tv.tv_usec += (timeout%1000) * 1000; - ndp_req->te = event_add_timed(nctx->ev, memctx, tv, - nss_dp_send_acct_timeout, ndp_req); - - /* Set up the reply handler */ - dbus_pending_call_set_notify(pending_reply, - nss_dp_send_acct_callback, - ndp_req, NULL); - dbus_message_unref(msg); - - return EOK; -} - -static int nss_dp_get_reply(DBusPendingCall *pending, - dbus_uint16_t *err_maj, - dbus_uint32_t *err_min, - const char **err_msg) -{ - DBusMessage *reply; - DBusError dbus_error; - dbus_bool_t ret; - int type; - int err = EOK; - - dbus_error_init(&dbus_error); - - reply = dbus_pending_call_steal_reply(pending); - if (!reply) { - /* reply should never be null. This function shouldn't be called - * until reply is valid or timeout has occurred. If reply is NULL - * here, something is seriously wrong and we should bail out. - */ - DEBUG(0, ("Severe error. A reply callback was called but no reply was received and no timeout occurred\n")); - - /* FIXME: Destroy this connection ? */ - err = EIO; - goto done; - } - - type = dbus_message_get_type(reply); - switch (type) { - case DBUS_MESSAGE_TYPE_METHOD_RETURN: - ret = dbus_message_get_args(reply, &dbus_error, - DBUS_TYPE_UINT16, err_maj, - DBUS_TYPE_UINT32, err_min, - DBUS_TYPE_STRING, err_msg, - DBUS_TYPE_INVALID); - if (!ret) { - DEBUG(1,("Filed to parse message\n")); - /* FIXME: Destroy this connection ? */ - if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error); - err = EIO; - goto done; - } - - DEBUG(4, ("Got reply (%u, %u, %s) from Data Provider\n", - (unsigned int)*err_maj, (unsigned int)*err_min, *err_msg)); - - break; - - case DBUS_MESSAGE_TYPE_ERROR: - DEBUG(0,("The Data Provider returned an error [%s]\n", - dbus_message_get_error_name(reply))); - /* Falling through to default intentionally*/ - default: - /* - * Timeout or other error occurred or something - * unexpected happened. - * It doesn't matter which, because either way we - * know that this connection isn't trustworthy. - * We'll destroy it now. - */ - - /* FIXME: Destroy this connection ? */ - err = EIO; - } - -done: - dbus_pending_call_unref(pending); - dbus_message_unref(reply); - - return err; -} - -static int nss_dp_identity(DBusMessage *message, struct sbus_conn_ctx *sconn) -{ - dbus_uint16_t version = DATA_PROVIDER_VERSION; - dbus_uint16_t clitype = DP_CLI_FRONTEND; - const char *cliname = "NSS"; - const char *nullname = ""; - DBusMessage *reply; - dbus_bool_t ret; - - DEBUG(4,("Sending ID reply: (%d,%d,%s)\n", - clitype, version, cliname)); - - reply = dbus_message_new_method_return(message); - if (!reply) return ENOMEM; - - ret = dbus_message_append_args(reply, - DBUS_TYPE_UINT16, &clitype, - DBUS_TYPE_UINT16, &version, - DBUS_TYPE_STRING, &cliname, - DBUS_TYPE_STRING, &nullname, - DBUS_TYPE_INVALID); - if (!ret) { - dbus_message_unref(reply); - return EIO; - } - - /* send reply back */ - sbus_conn_send_reply(sconn, reply); - dbus_message_unref(reply); - - return EOK; -} - -struct sbus_method nss_dp_methods[] = { - { DP_CLI_METHOD_IDENTITY, nss_dp_identity }, - { NULL, NULL } -}; - -struct nss_dp_pvt_ctx { - struct nss_ctx *nctx; - struct sbus_method *methods; - time_t last_retry; - int retries; -}; - -static int nss_dp_conn_destructor(void *data); -static void nss_dp_reconnect(struct event_context *ev, - struct timed_event *te, - struct timeval tv, void *data); - -static void nss_dp_conn_reconnect(struct nss_dp_pvt_ctx *pvt) -{ - struct nss_ctx *nctx; - struct timed_event *te; - struct timeval tv; - struct sbus_method_ctx *sm_ctx; - char *sbus_address; - time_t now; - int ret; - - now = time(NULL); - - /* reset retry if last reconnect was > 60 sec. ago */ - if (pvt->last_retry + 60 < now) pvt->retries = 0; - if (pvt->retries >= 3) { - DEBUG(4, ("Too many reconnect retries! Giving up\n")); - return; - } - - pvt->last_retry = now; - pvt->retries++; - - nctx = pvt->nctx; - - ret = dp_get_sbus_address(nctx, nctx->cdb, &sbus_address); - if (ret != EOK) { - DEBUG(0, ("Could not locate data provider address.\n")); - return; - } - - ret = dp_init_sbus_methods(nctx, pvt->methods, &sm_ctx); - if (ret != EOK) { - DEBUG(0, ("Could not initialize SBUS methods.\n")); - return; - } - - ret = sbus_client_init(nctx, nctx->ev, - sbus_address, sm_ctx, - pvt, nss_dp_conn_destructor, - &nctx->dp_ctx); - if (ret != EOK) { - DEBUG(4, ("Failed to reconnect [%d(%s)]!\n", ret, strerror(ret))); - - tv.tv_sec = now +5; - tv.tv_usec = 0; - te = event_add_timed(nctx->ev, nctx, tv, nss_dp_reconnect, pvt); - if (te == NULL) { - DEBUG(4, ("Failed to add timed event! Giving up\n")); - } else { - DEBUG(4, ("Retrying in 5 seconds\n")); - } - } -} - -static void nss_dp_reconnect(struct event_context *ev, - struct timed_event *te, - struct timeval tv, void *data) -{ - struct nss_dp_pvt_ctx *pvt; - - pvt = talloc_get_type(data, struct nss_dp_pvt_ctx); - - nss_dp_conn_reconnect(pvt); -} - -int nss_dp_conn_destructor(void *data) -{ - struct nss_dp_pvt_ctx *pvt; - struct sbus_conn_ctx *scon; - - scon = talloc_get_type(data, struct sbus_conn_ctx); - if (!scon) return 0; - - /* if this is a regular disconnect just quit */ - if (sbus_conn_disconnecting(scon)) return 0; - - pvt = talloc_get_type(sbus_conn_get_private_data(scon), - struct nss_dp_pvt_ctx); - if (pvt) return 0; - - nss_dp_conn_reconnect(pvt); - - return 0; -} - -int nss_dp_init(struct nss_ctx *nctx) -{ - struct nss_dp_pvt_ctx *pvt; - - pvt = talloc_zero(nctx, struct nss_dp_pvt_ctx); - if (!pvt) return ENOMEM; - - pvt->nctx = nctx; - pvt->methods = nss_dp_methods; - - nss_dp_conn_reconnect(pvt); - - return EOK; -} - |