From 1c48b5a62f73234ed26bb20f0ab345ab61cda0ab Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Thu, 18 Feb 2010 07:49:04 -0500 Subject: Rename server/ directory to src/ Also update BUILD.txt --- server/providers/data_provider_be.c | 1235 ----------------------------------- 1 file changed, 1235 deletions(-) delete mode 100644 server/providers/data_provider_be.c (limited to 'server/providers/data_provider_be.c') diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c deleted file mode 100644 index 93cae0702..000000000 --- a/server/providers/data_provider_be.c +++ /dev/null @@ -1,1235 +0,0 @@ -/* - SSSD - - Data Provider Process - - Copyright (C) Simo Sorce 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 . -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "popt.h" -#include "util/util.h" -#include "confdb/confdb.h" -#include "db/sysdb.h" -#include "dbus/dbus.h" -#include "sbus/sssd_dbus.h" -#include "providers/dp_backend.h" -#include "providers/fail_over.h" -#include "resolv/async_resolv.h" -#include "monitor/monitor_interfaces.h" - -#define MSG_TARGET_NO_CONFIGURED "sssd_be: The requested target is not configured" - -#define ACCESS_PERMIT "permit" -#define ACCESS_DENY "deny" -#define NO_PROVIDER "none" - -static int data_provider_res_init(DBusMessage *message, - struct sbus_connection *conn); -static int data_provider_go_offline(DBusMessage *message, - struct sbus_connection *conn); - -struct sbus_method monitor_be_methods[] = { - { MON_CLI_METHOD_PING, monitor_common_pong }, - { MON_CLI_METHOD_RES_INIT, data_provider_res_init }, - { MON_CLI_METHOD_OFFLINE, data_provider_go_offline }, - { NULL, NULL } -}; - -struct sbus_interface monitor_be_interface = { - MONITOR_INTERFACE, - MONITOR_PATH, - SBUS_DEFAULT_VTABLE, - monitor_be_methods, - NULL -}; - -static int client_registration(DBusMessage *message, struct sbus_connection *conn); -static int be_check_online(DBusMessage *message, struct sbus_connection *conn); -static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn); -static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn); - -struct sbus_method be_methods[] = { - { DP_METHOD_REGISTER, client_registration }, - { DP_METHOD_ONLINE, be_check_online }, - { DP_METHOD_GETACCTINFO, be_get_account_info }, - { DP_METHOD_PAMHANDLER, be_pam_handler }, - { NULL, NULL } -}; - -struct sbus_interface be_interface = { - DP_INTERFACE, - DP_PATH, - SBUS_DEFAULT_VTABLE, - be_methods, - NULL -}; - -static struct bet_data bet_data[] = { - {BET_NULL, NULL, NULL}, - {BET_ID, CONFDB_DOMAIN_ID_PROVIDER, "sssm_%s_init"}, - {BET_AUTH, CONFDB_DOMAIN_AUTH_PROVIDER, "sssm_%s_auth_init"}, - {BET_ACCESS, CONFDB_DOMAIN_ACCESS_PROVIDER, "sssm_%s_access_init"}, - {BET_CHPASS, CONFDB_DOMAIN_CHPASS_PROVIDER, "sssm_%s_chpass_init"}, - {BET_MAX, NULL, NULL} -}; - -struct be_async_req { - be_req_fn_t fn; - struct be_req *req; -}; - -static void be_async_req_handler(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval tv, void *pvt) -{ - struct be_async_req *async_req; - - async_req = talloc_get_type(pvt, struct be_async_req); - - async_req->fn(async_req->req); -} - -static int be_file_request(struct be_ctx *ctx, - be_req_fn_t fn, - struct be_req *req) -{ - struct be_async_req *areq; - struct tevent_timer *te; - struct timeval tv; - - if (!fn || !req) return EINVAL; - - areq = talloc(req, struct be_async_req); - if (!areq) { - return ENOMEM; - } - areq->fn = fn; - areq->req = req; - - /* fire immediately */ - tv.tv_sec = 0; - tv.tv_usec = 0; - - te = tevent_add_timer(ctx->ev, req, tv, be_async_req_handler, areq); - if (te == NULL) { - return EIO; - } - - return EOK; -} - -bool be_is_offline(struct be_ctx *ctx) -{ - time_t now = time(NULL); - - /* check if we are past the offline blackout timeout */ - /* FIXME: get offline_timeout from configuration */ - if (ctx->offstat.went_offline + 60 < now) { - ctx->offstat.offline = false; - } - - return ctx->offstat.offline; -} - -void be_mark_offline(struct be_ctx *ctx) -{ - DEBUG(8, ("Going offline!\n")); - - ctx->offstat.went_offline = time(NULL); - ctx->offstat.offline = true; -} - -static int be_check_online(DBusMessage *message, struct sbus_connection *conn) -{ - struct be_client *becli; - DBusMessage *reply; - DBusConnection *dbus_conn; - dbus_bool_t dbret; - void *user_data; - dbus_uint16_t online; - dbus_uint16_t err_maj = 0; - dbus_uint32_t err_min = 0; - static const char *err_msg = "Success"; - - user_data = sbus_conn_get_private_data(conn); - if (!user_data) return EINVAL; - becli = talloc_get_type(user_data, struct be_client); - if (!becli) return EINVAL; - - reply = dbus_message_new_method_return(message); - if (!reply) return ENOMEM; - - if (be_is_offline(becli->bectx)) { - online = MOD_OFFLINE; - } else { - online = MOD_ONLINE; - } - - dbret = dbus_message_append_args(reply, - DBUS_TYPE_UINT16, &online, - DBUS_TYPE_UINT16, &err_maj, - DBUS_TYPE_UINT32, &err_min, - DBUS_TYPE_STRING, &err_msg, - DBUS_TYPE_INVALID); - if (!dbret) { - DEBUG(1, ("Failed to generate dbus reply\n")); - return EIO; - } - - dbus_conn = sbus_get_connection(becli->conn); - dbus_connection_send(dbus_conn, reply, NULL); - dbus_message_unref(reply); - - DEBUG(4, ("Request processed. Returned %d,%d,%s\n", - err_maj, err_min, err_msg)); - - return EOK; -} - -static char *dp_err_to_string(TALLOC_CTX *memctx, int dp_err_type, int errnum) -{ - switch (dp_err_type) { - case DP_ERR_OK: - return talloc_strdup(memctx, "Success"); - break; - - case DP_ERR_OFFLINE: - return talloc_asprintf(memctx, - "Provider is Offline (%s)", - strerror(errnum)); - break; - - case DP_ERR_TIMEOUT: - return talloc_asprintf(memctx, - "Request timed out (%s)", - strerror(errnum)); - break; - - case DP_ERR_FATAL: - default: - return talloc_asprintf(memctx, - "Internal Error (%s)", - strerror(errnum)); - break; - } - - return NULL; -} - - -static void acctinfo_callback(struct be_req *req, - int dp_err_type, - int errnum, - const char *errstr) -{ - DBusMessage *reply; - DBusConnection *dbus_conn; - dbus_bool_t dbret; - dbus_uint16_t err_maj = 0; - dbus_uint32_t err_min = 0; - const char *err_msg = NULL; - - reply = (DBusMessage *)req->pvt; - - if (reply) { - /* Return a reply if one was requested - * There may not be one if this request began - * while we were offline - */ - - err_maj = dp_err_type; - err_min = errnum; - if (errstr) { - err_msg = errstr; - } else { - err_msg = dp_err_to_string(req, dp_err_type, errnum); - } - if (!err_msg) { - DEBUG(1, ("Failed to set err_msg, Out of memory?\n")); - err_msg = "OOM"; - } - - dbret = dbus_message_append_args(reply, - DBUS_TYPE_UINT16, &err_maj, - DBUS_TYPE_UINT32, &err_min, - DBUS_TYPE_STRING, &err_msg, - DBUS_TYPE_INVALID); - if (!dbret) { - DEBUG(1, ("Failed to generate dbus reply\n")); - return; - } - - dbus_conn = sbus_get_connection(req->becli->conn); - dbus_connection_send(dbus_conn, reply, NULL); - dbus_message_unref(reply); - - DEBUG(4, ("Request processed. Returned %d,%d,%s\n", - err_maj, err_min, err_msg)); - } - - /* finally free the request */ - talloc_free(req); -} - -static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn) -{ - struct be_acct_req *req; - struct be_req *be_req; - struct be_client *becli; - DBusMessage *reply; - DBusError dbus_error; - dbus_bool_t dbret; - void *user_data; - uint32_t type; - char *filter; - int filter_type; - uint32_t attr_type; - char *filter_val; - int ret; - dbus_uint16_t err_maj; - dbus_uint32_t err_min; - const char *err_msg; - - be_req = NULL; - - user_data = sbus_conn_get_private_data(conn); - if (!user_data) return EINVAL; - becli = talloc_get_type(user_data, struct be_client); - if (!becli) return EINVAL; - - dbus_error_init(&dbus_error); - - ret = dbus_message_get_args(message, &dbus_error, - DBUS_TYPE_UINT32, &type, - DBUS_TYPE_UINT32, &attr_type, - DBUS_TYPE_STRING, &filter, - DBUS_TYPE_INVALID); - if (!ret) { - DEBUG(1,("Failed, to parse message!\n")); - if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error); - return EIO; - } - - DEBUG(4, ("Got request for [%u][%d][%s]\n", type, attr_type, filter)); - - reply = dbus_message_new_method_return(message); - if (!reply) return ENOMEM; - - /* If we are offline and fast reply was requested - * return offline immediately - */ - if ((type & BE_REQ_FAST) && becli->bectx->offstat.offline) { - /* Send back an immediate reply */ - err_maj = DP_ERR_OFFLINE; - err_min = EAGAIN; - err_msg = "Fast reply - offline"; - - dbret = dbus_message_append_args(reply, - DBUS_TYPE_UINT16, &err_maj, - DBUS_TYPE_UINT32, &err_min, - DBUS_TYPE_STRING, &err_msg, - DBUS_TYPE_INVALID); - if (!dbret) return EIO; - - DEBUG(4, ("Request processed. Returned %d,%d,%s\n", - err_maj, err_min, err_msg)); - - sbus_conn_send_reply(conn, reply); - dbus_message_unref(reply); - reply = NULL; - /* This reply will be queued and sent - * when we reenter the mainloop. - * - * Continue processing in case we are - * going back online. - */ - } - - if ((attr_type != BE_ATTR_CORE) && - (attr_type != BE_ATTR_MEM) && - (attr_type != BE_ATTR_ALL)) { - /* Unrecognized attr type */ - err_maj = DP_ERR_FATAL; - err_min = EINVAL; - err_msg = "Invalid Attrs Parameter"; - goto done; - } - - if (filter) { - if (strncmp(filter, "name=", 5) == 0) { - filter_type = BE_FILTER_NAME; - filter_val = &filter[5]; - } else if (strncmp(filter, "idnumber=", 9) == 0) { - filter_type = BE_FILTER_IDNUM; - filter_val = &filter[9]; - } else { - err_maj = DP_ERR_FATAL; - err_min = EINVAL; - err_msg = "Invalid Filter"; - goto done; - } - } else { - err_maj = DP_ERR_FATAL; - err_min = EINVAL; - err_msg = "Missing Filter Parameter"; - goto done; - } - - /* process request */ - be_req = talloc(becli, struct be_req); - if (!be_req) { - err_maj = DP_ERR_FATAL; - err_min = ENOMEM; - err_msg = "Out of memory"; - goto done; - } - be_req->becli = becli; - be_req->be_ctx = becli->bectx; - be_req->fn = acctinfo_callback; - be_req->pvt = reply; - - req = talloc(be_req, struct be_acct_req); - if (!req) { - err_maj = DP_ERR_FATAL; - err_min = ENOMEM; - err_msg = "Out of memory"; - goto done; - } - req->entry_type = type; - req->attr_type = (int)attr_type; - req->filter_type = filter_type; - req->filter_value = talloc_strdup(req, filter_val); - - be_req->req_data = req; - - ret = be_file_request(becli->bectx, - becli->bectx->bet_info[BET_ID].bet_ops->handler, - be_req); - if (ret != EOK) { - err_maj = DP_ERR_FATAL; - err_min = ret; - err_msg = "Failed to file request"; - goto done; - } - - return EOK; - -done: - if (be_req) { - talloc_free(be_req); - } - - if (reply) { - dbret = dbus_message_append_args(reply, - DBUS_TYPE_UINT16, &err_maj, - DBUS_TYPE_UINT32, &err_min, - DBUS_TYPE_STRING, &err_msg, - DBUS_TYPE_INVALID); - if (!dbret) return EIO; - - DEBUG(4, ("Request processed. Returned %d,%d,%s\n", - err_maj, err_min, err_msg)); - - /* send reply back */ - sbus_conn_send_reply(conn, reply); - dbus_message_unref(reply); - } - - return EOK; -} - -static void be_pam_handler_callback(struct be_req *req, - int dp_err_type, - int errnum, - const char *errstr) -{ - struct pam_data *pd; - DBusMessage *reply; - DBusConnection *dbus_conn; - dbus_bool_t dbret; - - DEBUG(4, ("Backend returned: (%d, %d, %s) [%s]\n", - dp_err_type, errnum, errstr?errstr:"", - dp_err_to_string(req, dp_err_type, 0))); - - pd = talloc_get_type(req->req_data, struct pam_data); - - DEBUG(4, ("Sending result [%d][%s]\n", pd->pam_status, pd->domain)); - reply = (DBusMessage *)req->pvt; - dbret = dp_pack_pam_response(reply, pd); - if (!dbret) { - DEBUG(1, ("Failed to generate dbus reply\n")); - dbus_message_unref(reply); - return; - } - - dbus_conn = sbus_get_connection(req->becli->conn); - dbus_connection_send(dbus_conn, reply, NULL); - dbus_message_unref(reply); - - DEBUG(4, ("Sent result [%d][%s]\n", pd->pam_status, pd->domain)); - - talloc_free(req); -} - -static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn) -{ - DBusError dbus_error; - DBusMessage *reply; - struct be_client *becli; - dbus_bool_t ret; - void *user_data; - struct pam_data *pd = NULL; - struct be_req *be_req = NULL; - enum bet_type target = BET_NULL; - - user_data = sbus_conn_get_private_data(conn); - if (!user_data) return EINVAL; - becli = talloc_get_type(user_data, struct be_client); - if (!becli) return EINVAL; - - reply = dbus_message_new_method_return(message); - if (!reply) { - DEBUG(1, ("dbus_message_new_method_return failed, cannot send reply.\n")); - return ENOMEM; - } - - be_req = talloc_zero(becli, struct be_req); - if (!be_req) { - DEBUG(7, ("talloc_zero failed.\n")); - goto done; - } - - be_req->becli = becli; - be_req->be_ctx = becli->bectx; - be_req->fn = be_pam_handler_callback; - be_req->pvt = reply; - - pd = talloc_zero(be_req, struct pam_data); - if (!pd) { - talloc_free(be_req); - return ENOMEM; - } - - pd->pam_status = PAM_SYSTEM_ERR; - pd->domain = talloc_strdup(pd, becli->bectx->domain->name); - if (pd->domain == NULL) { - talloc_free(be_req); - return ENOMEM; - } - - dbus_error_init(&dbus_error); - - ret = dp_unpack_pam_request(message, pd, &dbus_error); - if (!ret) { - DEBUG(1,("Failed, to parse message!\n")); - talloc_free(be_req); - return EIO; - } - - DEBUG(4, ("Got request with the following data\n")); - DEBUG_PAM_DATA(4, pd); - - switch (pd->cmd) { - case SSS_PAM_AUTHENTICATE: - target = BET_AUTH; - break; - case SSS_PAM_ACCT_MGMT: - target = BET_ACCESS; - break; - case SSS_PAM_CHAUTHTOK: - case SSS_PAM_CHAUTHTOK_PRELIM: - target = BET_CHPASS; - break; - case SSS_PAM_SETCRED: - case SSS_PAM_OPEN_SESSION: - case SSS_PAM_CLOSE_SESSION: - pd->pam_status = PAM_SUCCESS; - goto done; - break; - default: - DEBUG(7, ("Unsupported PAM command [%d].\n", pd->cmd)); - pd->pam_status = PAM_MODULE_UNKNOWN; - goto done; - } - - /* return an error if corresponding backend target is not configured */ - if (!becli->bectx->bet_info[target].bet_ops) { - DEBUG(7, ("Undefined backend target.\n")); - pd->pam_status = PAM_MODULE_UNKNOWN; - ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, - sizeof(MSG_TARGET_NO_CONFIGURED), - (const uint8_t *) MSG_TARGET_NO_CONFIGURED); - if (ret != EOK) { - DEBUG(1, ("pam_add_response failed.\n")); - } - goto done; - } - - be_req->req_data = pd; - - ret = be_file_request(becli->bectx, - becli->bectx->bet_info[target].bet_ops->handler, - be_req); - if (ret != EOK) { - DEBUG(7, ("be_file_request failed.\n")); - goto done; - } - - return EOK; - -done: - - DEBUG(4, ("Sending result [%d][%s]\n", - pd->pam_status, pd->domain)); - - ret = dp_pack_pam_response(reply, pd); - if (!ret) { - DEBUG(1, ("Failed to generate dbus reply\n")); - talloc_free(be_req); - dbus_message_unref(reply); - return EIO; - } - - /* send reply back immediately */ - sbus_conn_send_reply(conn, reply); - dbus_message_unref(reply); - - talloc_free(be_req); - - return EOK; -} - -static int be_client_destructor(void *ctx) -{ - struct be_client *becli = talloc_get_type(ctx, struct be_client); - if (becli->bectx) { - if (becli->bectx->nss_cli == becli) { - DEBUG(4, ("Removed NSS client\n")); - becli->bectx->nss_cli = NULL; - } else if (becli->bectx->pam_cli == becli) { - DEBUG(4, ("Removed PAM client\n")); - becli->bectx->pam_cli = NULL; - } else { - DEBUG(2, ("Unknown client removed ...\n")); - } - } - return 0; -} - -static int client_registration(DBusMessage *message, - struct sbus_connection *conn) -{ - dbus_uint16_t version = DATA_PROVIDER_VERSION; - struct be_client *becli; - DBusMessage *reply; - DBusError dbus_error; - dbus_uint16_t cli_ver; - char *cli_name; - char *cli_domain; - dbus_bool_t dbret; - void *data; - - data = sbus_conn_get_private_data(conn); - becli = talloc_get_type(data, struct be_client); - if (!becli) { - DEBUG(0, ("Connection holds no valid init data\n")); - return EINVAL; - } - - /* First thing, cancel the timeout */ - DEBUG(4, ("Cancel DP ID timeout [%p]\n", becli->timeout)); - talloc_zfree(becli->timeout); - - dbus_error_init(&dbus_error); - - dbret = dbus_message_get_args(message, &dbus_error, - DBUS_TYPE_UINT16, &cli_ver, - DBUS_TYPE_STRING, &cli_name, - DBUS_TYPE_STRING, &cli_domain, - DBUS_TYPE_INVALID); - if (!dbret) { - DEBUG(1, ("Failed to parse message, killing connection\n")); - if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error); - sbus_disconnect(conn); - /* FIXME: should we just talloc_zfree(conn) ? */ - return EIO; - } - - if (strcasecmp(cli_name, "NSS") == 0) { - becli->bectx->nss_cli = becli; - } else if (strcasecmp(cli_name, "PAM") == 0) { - becli->bectx->pam_cli = becli; - } else { - DEBUG(1, ("Unknown client! [%s]\n", cli_name)); - } - talloc_set_destructor((TALLOC_CTX *)becli, be_client_destructor); - - DEBUG(4, ("Added Frontend client [%s]\n", cli_name)); - - /* reply that all is ok */ - reply = dbus_message_new_method_return(message); - if (!reply) { - DEBUG(0, ("Dbus Out of memory!\n")); - return ENOMEM; - } - - dbret = dbus_message_append_args(reply, - DBUS_TYPE_UINT16, &version, - DBUS_TYPE_INVALID); - if (!dbret) { - DEBUG(0, ("Failed to build dbus reply\n")); - dbus_message_unref(reply); - sbus_disconnect(conn); - return EIO; - } - - /* send reply back */ - sbus_conn_send_reply(conn, reply); - dbus_message_unref(reply); - - becli->initialized = true; - return EOK; -} - -static void init_timeout(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval t, void *ptr) -{ - struct be_client *becli; - - DEBUG(2, ("Client timed out before Identification [%p]!\n", te)); - - becli = talloc_get_type(ptr, struct be_client); - - sbus_disconnect(becli->conn); - talloc_zfree(becli); -} - -static int be_client_init(struct sbus_connection *conn, void *data) -{ - struct be_ctx *bectx; - struct be_client *becli; - struct timeval tv; - - bectx = talloc_get_type(data, struct be_ctx); - - /* hang off this memory to the connection so that when the connection - * is freed we can potentially call a destructor */ - - becli = talloc(conn, struct be_client); - if (!becli) { - DEBUG(0,("Out of memory?!\n")); - talloc_zfree(conn); - return ENOMEM; - } - becli->bectx = bectx; - becli->conn = conn; - becli->initialized = false; - - /* 5 seconds should be plenty */ - tv = tevent_timeval_current_ofs(5, 0); - - becli->timeout = tevent_add_timer(bectx->ev, becli, - tv, init_timeout, becli); - if (!becli->timeout) { - DEBUG(0,("Out of memory?!\n")); - talloc_zfree(conn); - return ENOMEM; - } - DEBUG(4, ("Set-up Backend ID timeout [%p]\n", becli->timeout)); - - /* Attach the client context to the connection context, so that it is - * always available when we need to manage the connection. */ - sbus_conn_set_private_data(conn, becli); - - return EOK; -} - -/* be_srv_init - * set up per-domain sbus channel */ -static int be_srv_init(struct be_ctx *ctx) -{ - char *sbus_address; - int ret; - - /* Set up SBUS connection to the monitor */ - ret = dp_get_sbus_address(ctx, &sbus_address, ctx->domain->name); - if (ret != EOK) { - DEBUG(0, ("Could not get sbus backend address.\n")); - return ret; - } - - ret = sbus_new_server(ctx, ctx->ev, sbus_address, - &be_interface, &ctx->sbus_srv, - be_client_init, ctx); - if (ret != EOK) { - DEBUG(0, ("Could not set up sbus server.\n")); - return ret; - } - - return EOK; -} - -/* mon_cli_init - * sbus channel to the monitor daemon */ -static int mon_cli_init(struct be_ctx *ctx) -{ - char *sbus_address; - int ret; - - /* Set up SBUS connection to the monitor */ - ret = monitor_get_sbus_address(ctx, &sbus_address); - if (ret != EOK) { - DEBUG(0, ("Could not locate monitor address.\n")); - return ret; - } - - ret = sbus_client_init(ctx, ctx->ev, sbus_address, - &monitor_be_interface, &ctx->mon_conn, - NULL, ctx); - if (ret != EOK) { - DEBUG(0, ("Failed to connect to monitor services.\n")); - return ret; - } - - /* Identify ourselves to the monitor */ - ret = monitor_common_send_id(ctx->mon_conn, - ctx->identity, - DATA_PROVIDER_VERSION); - if (ret != EOK) { - DEBUG(0, ("Failed to identify to the monitor!\n")); - return ret; - } - - return EOK; -} - -static void be_target_access_permit(struct be_req *be_req) -{ - struct pam_data *pd = talloc_get_type(be_req->req_data, struct pam_data); - DEBUG(9, ("be_target_access_permit called, returning PAM_SUCCESS.\n")); - - pd->pam_status = PAM_SUCCESS; - be_req->fn(be_req, DP_ERR_OK, PAM_SUCCESS, NULL); -} - -static struct bet_ops be_target_access_permit_ops = { - .check_online = NULL, - .handler = be_target_access_permit, - .finalize = NULL -}; - -static void be_target_access_deny(struct be_req *be_req) -{ - struct pam_data *pd = talloc_get_type(be_req->req_data, struct pam_data); - DEBUG(9, ("be_target_access_deny called, returning PAM_PERM_DENIED.\n")); - - pd->pam_status = PAM_PERM_DENIED; - be_req->fn(be_req, DP_ERR_OK, PAM_PERM_DENIED, NULL); -} - -static struct bet_ops be_target_access_deny_ops = { - .check_online = NULL, - .handler = be_target_access_deny, - .finalize = NULL -}; - -static int load_backend_module(struct be_ctx *ctx, - enum bet_type bet_type, - struct bet_info *bet_info, - const char *default_mod_name) -{ - TALLOC_CTX *tmp_ctx; - int ret = EINVAL; - bool already_loaded = false; - int lb=0; - char *mod_name = NULL; - char *path = NULL; - void *handle; - char *mod_init_fn_name = NULL; - bet_init_fn_t mod_init_fn = NULL; - - (*bet_info).mod_name = NULL; - (*bet_info).bet_ops = NULL; - (*bet_info).pvt_bet_data = NULL; - - if (bet_type <= BET_NULL || bet_type >= BET_MAX || - bet_type != bet_data[bet_type].bet_type) { - DEBUG(2, ("invalid bet_type or bet_data corrupted.\n")); - return EINVAL; - } - - tmp_ctx = talloc_new(ctx); - if (!tmp_ctx) { - DEBUG(7, ("talloc_new failed.\n")); - return ENOMEM; - } - - ret = confdb_get_string(ctx->cdb, tmp_ctx, ctx->conf_path, - bet_data[bet_type].option_name, NULL, - &mod_name); - if (ret != EOK) { - ret = EFAULT; - goto done; - } - if (!mod_name) { - if (default_mod_name != NULL) { - DEBUG(5, ("no module name found in confdb, using [%s].\n", - default_mod_name)); - mod_name = talloc_strdup(ctx, default_mod_name); - } else { - ret = ENOENT; - goto done; - } - } - - if (strcasecmp(mod_name, NO_PROVIDER) == 0) { - ret = ENOENT; - goto done; - } - - if (bet_type == BET_ACCESS) { - if (strcmp(mod_name, ACCESS_PERMIT) == 0) { - (*bet_info).bet_ops = &be_target_access_permit_ops; - (*bet_info).pvt_bet_data = NULL; - (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_PERMIT); - - ret = EOK; - goto done; - } - if (strcmp(mod_name, ACCESS_DENY) == 0) { - (*bet_info).bet_ops = &be_target_access_deny_ops; - (*bet_info).pvt_bet_data = NULL; - (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_DENY); - - ret = EOK; - goto done; - } - } - - mod_init_fn_name = talloc_asprintf(tmp_ctx, - bet_data[bet_type].mod_init_fn_name_fmt, - mod_name); - if (mod_init_fn_name == NULL) { - DEBUG(7, ("talloc_asprintf failed\n")); - ret = ENOMEM; - goto done; - } - - - lb = 0; - while(ctx->loaded_be[lb].be_name != NULL) { - if (strncmp(ctx->loaded_be[lb].be_name, mod_name, - strlen(mod_name)) == 0) { - DEBUG(7, ("Backend [%s] already loaded.\n", mod_name)); - already_loaded = true; - break; - } - - ++lb; - if (lb >= BET_MAX) { - DEBUG(2, ("Backend context corrupted.\n")); - ret = EINVAL; - goto done; - } - } - - if (!already_loaded) { - path = talloc_asprintf(tmp_ctx, "%s/libsss_%s.so", - DATA_PROVIDER_PLUGINS_PATH, mod_name); - if (!path) { - ret = ENOMEM; - goto done; - } - - DEBUG(7, ("Loading backend [%s] with path [%s].\n", mod_name, path)); - handle = dlopen(path, RTLD_NOW); - if (!handle) { - DEBUG(0, ("Unable to load %s module with path (%s), error: %s\n", - mod_name, path, dlerror())); - ret = ELIBACC; - goto done; - } - - ctx->loaded_be[lb].be_name = talloc_strdup(ctx, mod_name); - ctx->loaded_be[lb].handle = handle; - } - - mod_init_fn = (bet_init_fn_t)dlsym(ctx->loaded_be[lb].handle, - mod_init_fn_name); - if (mod_init_fn == NULL) { - if (default_mod_name != NULL && - strcmp(default_mod_name, mod_name) == 0 ) { - /* If the default is used and fails we indicate this to the caller - * by returning ENOENT. Ths way the caller can decide how to - * handle the different types of error conditions. */ - ret = ENOENT; - } else { - DEBUG(0, ("Unable to load init fn %s from module %s, error: %s\n", - mod_init_fn_name, mod_name, dlerror())); - ret = ELIBBAD; - } - goto done; - } - - ret = mod_init_fn(ctx, &(*bet_info).bet_ops, &(*bet_info).pvt_bet_data); - if (ret != EOK) { - DEBUG(0, ("Error (%d) in module (%s) initialization (%s)!\n", - ret, mod_name, mod_init_fn_name)); - goto done; - } - - (*bet_info).mod_name = talloc_strdup(ctx, mod_name); - - ret = EOK; - -done: - talloc_free(tmp_ctx); - return ret; -} - -static void signal_be_offline(struct tevent_context *ev, - struct tevent_signal *se, - int signum, - int count, - void *siginfo, - void *private_data) -{ - struct be_ctx *ctx = talloc_get_type(private_data, struct be_ctx); - be_mark_offline(ctx); -} - -int be_process_init(TALLOC_CTX *mem_ctx, - const char *be_domain, - struct tevent_context *ev, - struct confdb_ctx *cdb) -{ - struct be_ctx *ctx; - struct tevent_signal *tes; - int ret; - - ctx = talloc_zero(mem_ctx, struct be_ctx); - if (!ctx) { - DEBUG(0, ("fatal error initializing be_ctx\n")); - return ENOMEM; - } - ctx->ev = ev; - ctx->cdb = cdb; - ctx->identity = talloc_asprintf(ctx, "%%BE_%s", be_domain); - ctx->conf_path = talloc_asprintf(ctx, CONFDB_DOMAIN_PATH_TMPL, be_domain); - if (!ctx->identity || !ctx->conf_path) { - DEBUG(0, ("Out of memory!?\n")); - return ENOMEM; - } - - ret = be_init_failover(ctx); - if (ret != EOK) { - DEBUG(0, ("fatal error initializing failover context\n")); - return ret; - } - - ret = confdb_get_domain(cdb, be_domain, &ctx->domain); - if (ret != EOK) { - DEBUG(0, ("fatal error retrieving domain configuration\n")); - return ret; - } - - ret = sysdb_domain_init(ctx, ev, ctx->domain, DB_PATH, &ctx->sysdb); - if (ret != EOK) { - DEBUG(0, ("fatal error opening cache database\n")); - return ret; - } - - ret = mon_cli_init(ctx); - if (ret != EOK) { - DEBUG(0, ("fatal error setting up monitor bus\n")); - return ret; - } - - ret = be_srv_init(ctx); - if (ret != EOK) { - DEBUG(0, ("fatal error setting up server bus\n")); - return ret; - } - - ret = load_backend_module(ctx, BET_ID, - &ctx->bet_info[BET_ID], NULL); - if (ret != EOK) { - DEBUG(0, ("fatal error initializing data providers\n")); - return ret; - } - DEBUG(9, ("ID backend target successfully loaded from provider [%s].\n", - ctx->bet_info[BET_ID].mod_name)); - - ret = load_backend_module(ctx, BET_AUTH, - &ctx->bet_info[BET_AUTH], - ctx->bet_info[BET_ID].mod_name); - if (ret != EOK) { - if (ret != ENOENT) { - DEBUG(0, ("fatal error initializing data providers\n")); - return ret; - } - DEBUG(1, ("No authentication module provided for [%s] !!\n", - be_domain)); - } else { - DEBUG(9, ("AUTH backend target successfully loaded " - "from provider [%s].\n", ctx->bet_info[BET_AUTH].mod_name)); - } - - ret = load_backend_module(ctx, BET_ACCESS, &ctx->bet_info[BET_ACCESS], - ACCESS_PERMIT); - if (ret != EOK) { - DEBUG(0, ("Failed to setup ACCESS backend.\n")); - return ret; - } - DEBUG(9, ("ACCESS backend target successfully loaded " - "from provider [%s].\n", ctx->bet_info[BET_ACCESS].mod_name)); - - ret = load_backend_module(ctx, BET_CHPASS, - &ctx->bet_info[BET_CHPASS], - ctx->bet_info[BET_AUTH].mod_name); - if (ret != EOK) { - if (ret != ENOENT) { - DEBUG(0, ("fatal error initializing data providers\n")); - return ret; - } - DEBUG(1, ("No change password module provided for [%s] !!\n", - be_domain)); - } else { - DEBUG(9, ("CHPASS backend target successfully loaded " - "from provider [%s].\n", ctx->bet_info[BET_CHPASS].mod_name)); - } - - /* Handle SIGUSR1 to force offline behavior */ - BlockSignals(false, SIGUSR1); - tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0, - signal_be_offline, ctx); - if (tes == NULL) { - return EIO; - } - - return EOK; -} - -int main(int argc, const char *argv[]) -{ - int opt; - poptContext pc; - char *be_domain = NULL; - char *srv_name = NULL; - char *conf_entry = NULL; - struct main_context *main_ctx; - int ret; - - struct poptOption long_options[] = { - POPT_AUTOHELP - SSSD_MAIN_OPTS - {"domain", 0, POPT_ARG_STRING, &be_domain, 0, - _("Domain of the information provider (mandatory)"), NULL }, - POPT_TABLEEND - }; - - pc = poptGetContext(argv[0], argc, argv, long_options, 0); - while((opt = poptGetNextOpt(pc)) != -1) { - switch(opt) { - default: - fprintf(stderr, "\nInvalid option %s: %s\n\n", - poptBadOption(pc, 0), poptStrerror(opt)); - poptPrintUsage(pc, stderr, 0); - return 1; - } - } - - if (be_domain == NULL) { - fprintf(stderr, "\nMissing option, --domain is a mandatory option.\n\n"); - poptPrintUsage(pc, stderr, 0); - return 1; - } - - poptFreeContext(pc); - - - /* set up things like debug , signals, daemonization, etc... */ - debug_log_file = talloc_asprintf(NULL, "sssd_%s", be_domain); - if (!debug_log_file) return 2; - - srv_name = talloc_asprintf(NULL, "sssd[be[%s]]", be_domain); - if (!srv_name) return 2; - - conf_entry = talloc_asprintf(NULL, CONFDB_DOMAIN_PATH_TMPL, be_domain); - if (!conf_entry) return 2; - - ret = server_setup(srv_name, 0, conf_entry, &main_ctx); - if (ret != EOK) { - DEBUG(0, ("Could not set up mainloop [%d]\n", ret)); - return 2; - } - - ret = die_if_parent_died(); - if (ret != EOK) { - /* This is not fatal, don't return */ - DEBUG(2, ("Could not set up to exit when parent process does\n")); - } - - ret = be_process_init(main_ctx, - be_domain, - main_ctx->event_ctx, - main_ctx->confdb_ctx); - if (ret != EOK) { - DEBUG(0, ("Could not initialize backend [%d]\n", ret)); - return 3; - } - - DEBUG(1, ("Backend provider (%s) started!\n", be_domain)); - - /* loop on main */ - server_loop(main_ctx); - - return 0; -} - -static int data_provider_res_init(DBusMessage *message, - struct sbus_connection *conn) -{ - resolv_reread_configuration(); - - return monitor_common_res_init(message, conn); -} - -static int data_provider_go_offline(DBusMessage *message, - struct sbus_connection *conn) -{ - struct be_ctx *be_ctx; - be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx); - be_mark_offline(be_ctx); - return monitor_common_pong(message, conn); -} -- cgit