LCOV - code coverage report
Current view: top level - providers - data_provider_be.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 50 1379 3.6 %
Date: 2015-10-19 Functions: 7 64 10.9 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    Data Provider Process
       5             : 
       6             :    Copyright (C) Simo Sorce <ssorce@redhat.com>   2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include <stdio.h>
      23             : #include <unistd.h>
      24             : #include <fcntl.h>
      25             : #include <sys/types.h>
      26             : #include <sys/stat.h>
      27             : #include <sys/socket.h>
      28             : #include <sys/un.h>
      29             : #include <string.h>
      30             : #include <sys/time.h>
      31             : #include <errno.h>
      32             : #include <dlfcn.h>
      33             : #include <popt.h>
      34             : #include <dbus/dbus.h>
      35             : 
      36             : #include <security/pam_appl.h>
      37             : #include <security/pam_modules.h>
      38             : 
      39             : #include "util/util.h"
      40             : #include "confdb/confdb.h"
      41             : #include "db/sysdb.h"
      42             : #include "sbus/sssd_dbus.h"
      43             : #include "providers/dp_backend.h"
      44             : #include "providers/fail_over.h"
      45             : #include "providers/dp_refresh.h"
      46             : #include "providers/dp_ptask.h"
      47             : #include "util/child_common.h"
      48             : #include "resolv/async_resolv.h"
      49             : #include "monitor/monitor_interfaces.h"
      50             : 
      51             : #define MSG_TARGET_NO_CONFIGURED "sssd_be: The requested target is not configured"
      52             : 
      53             : #define ACCESS_PERMIT "permit"
      54             : #define ACCESS_DENY "deny"
      55             : #define NO_PROVIDER "none"
      56             : 
      57             : static int data_provider_res_init(struct sbus_request *dbus_req, void *data);
      58             : static int data_provider_go_offline(struct sbus_request *dbus_req, void *data);
      59             : static int data_provider_reset_offline(struct sbus_request *dbus_req, void *data);
      60             : static int data_provider_logrotate(struct sbus_request *dbus_req, void *data);
      61             : 
      62             : struct mon_cli_iface monitor_be_methods = {
      63             :     { &mon_cli_iface_meta, 0 },
      64             :     .ping = monitor_common_pong,
      65             :     .resInit = data_provider_res_init,
      66             :     .shutDown = NULL,
      67             :     .goOffline = data_provider_go_offline,
      68             :     .resetOffline = data_provider_reset_offline,
      69             :     .rotateLogs = data_provider_logrotate,
      70             :     .clearMemcache = NULL,
      71             :     .clearEnumCache = NULL,
      72             :     .sysbusReconnect = NULL,
      73             : };
      74             : 
      75             : static int client_registration(struct sbus_request *dbus_req, void *data);
      76             : static int be_get_account_info(struct sbus_request *dbus_req, void *user_data);
      77             : static int be_pam_handler(struct sbus_request *dbus_req, void *user_data);
      78             : static int be_sudo_handler(struct sbus_request *dbus_req, void *user_data);
      79             : static int be_autofs_handler(struct sbus_request *dbus_req, void *user_data);
      80             : static int be_host_handler(struct sbus_request *dbus_req, void *user_data);
      81             : static int be_get_subdomains(struct sbus_request *dbus_req, void *user_data);
      82             : 
      83             : struct data_provider_iface be_methods = {
      84             :     { &data_provider_iface_meta, 0 },
      85             :     .RegisterService = client_registration,
      86             :     .pamHandler = be_pam_handler,
      87             :     .sudoHandler = be_sudo_handler,
      88             :     .autofsHandler = be_autofs_handler,
      89             :     .hostHandler = be_host_handler,
      90             :     .getDomains = be_get_subdomains,
      91             :     .getAccountInfo = be_get_account_info,
      92             : };
      93             : 
      94             : static struct bet_data bet_data[] = {
      95             :     {BET_NULL, NULL, NULL},
      96             :     {BET_ID, CONFDB_DOMAIN_ID_PROVIDER, "sssm_%s_id_init"},
      97             :     {BET_AUTH, CONFDB_DOMAIN_AUTH_PROVIDER, "sssm_%s_auth_init"},
      98             :     {BET_ACCESS, CONFDB_DOMAIN_ACCESS_PROVIDER, "sssm_%s_access_init"},
      99             :     {BET_CHPASS, CONFDB_DOMAIN_CHPASS_PROVIDER, "sssm_%s_chpass_init"},
     100             :     {BET_SUDO, CONFDB_DOMAIN_SUDO_PROVIDER, "sssm_%s_sudo_init"},
     101             :     {BET_AUTOFS, CONFDB_DOMAIN_AUTOFS_PROVIDER, "sssm_%s_autofs_init"},
     102             :     {BET_SELINUX, CONFDB_DOMAIN_SELINUX_PROVIDER, "sssm_%s_selinux_init"},
     103             :     {BET_HOSTID, CONFDB_DOMAIN_HOSTID_PROVIDER, "sssm_%s_hostid_init"},
     104             :     {BET_SUBDOMAINS, CONFDB_DOMAIN_SUBDOMAINS_PROVIDER, "sssm_%s_subdomains_init"},
     105             :     {BET_MAX, NULL, NULL}
     106             : };
     107             : 
     108             : struct bet_queue_item {
     109             :     struct bet_queue_item *prev;
     110             :     struct bet_queue_item *next;
     111             : 
     112             :     TALLOC_CTX *mem_ctx;
     113             :     struct be_req *be_req;
     114             :     be_req_fn_t fn;
     115             : 
     116             : };
     117             : 
     118             : #define REQ_PHASE_ACCESS 0
     119             : #define REQ_PHASE_SELINUX 1
     120             : 
     121             : struct be_req {
     122             :     struct be_client *becli;
     123             :     struct be_ctx *be_ctx;
     124             :     struct sss_domain_info *domain;
     125             :     void *req_data;
     126             : 
     127             :     be_async_callback_t fn;
     128             :     void *pvt;
     129             : 
     130             :     /* This is utilized in access provider
     131             :      * request handling to indicate if access or
     132             :      * selinux provider is calling the callback.
     133             :      */
     134             :     int phase;
     135             : 
     136             :     struct be_req *prev;
     137             :     struct be_req *next;
     138             : };
     139             : 
     140           0 : static int be_req_destructor(struct be_req *be_req)
     141             : {
     142           0 :     DLIST_REMOVE(be_req->be_ctx->active_requests, be_req);
     143             : 
     144           0 :     return 0;
     145             : }
     146             : 
     147           0 : struct be_req *be_req_create(TALLOC_CTX *mem_ctx,
     148             :                              struct be_client *becli, struct be_ctx *be_ctx,
     149             :                              be_async_callback_t fn, void *pvt_fn_data)
     150             : {
     151             :     struct be_req *be_req;
     152             : 
     153           0 :     be_req = talloc_zero(mem_ctx, struct be_req);
     154           0 :     if (be_req == NULL) return NULL;
     155             : 
     156           0 :     be_req->becli = becli;
     157           0 :     be_req->be_ctx = be_ctx;
     158           0 :     be_req->domain = be_ctx->domain;
     159           0 :     be_req->fn = fn;
     160           0 :     be_req->pvt = pvt_fn_data;
     161             : 
     162             :     /* Add this request to active request list and make sure it is
     163             :      * removed on termination. */
     164           0 :     DLIST_ADD(be_ctx->active_requests, be_req);
     165           0 :     talloc_set_destructor(be_req, be_req_destructor);
     166             : 
     167           0 :     return be_req;
     168             : }
     169             : 
     170           0 : static errno_t be_req_set_domain(struct be_req *be_req, const char *domain)
     171             : {
     172           0 :     struct sss_domain_info *dom = NULL;
     173             : 
     174           0 :     dom = find_domain_by_name(be_req->be_ctx->domain, domain, true);
     175           0 :     if (dom == NULL) {
     176           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unknown domain [%s]!\n", domain);
     177           0 :         return ERR_DOMAIN_NOT_FOUND;
     178             :     }
     179             : 
     180           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Changing request domain from [%s] to [%s]\n",
     181             :                               be_req->domain->name, dom->name);
     182           0 :     be_req->domain = dom;
     183             : 
     184           0 :     return EOK;
     185             : }
     186             : 
     187           0 : struct be_ctx *be_req_get_be_ctx(struct be_req *be_req)
     188             : {
     189           0 :     return be_req->be_ctx;
     190             : }
     191             : 
     192           0 : void *be_req_get_data(struct be_req *be_req)
     193             : {
     194           0 :     return be_req->req_data;
     195             : }
     196             : 
     197           0 : void be_req_terminate(struct be_req *be_req,
     198             :                       int dp_err_type, int errnum, const char *errstr)
     199             : {
     200           0 :     if (be_req->fn == NULL) return;
     201           0 :     be_req->fn(be_req, dp_err_type, errnum, errstr);
     202             : }
     203             : 
     204           1 : void be_terminate_domain_requests(struct be_ctx *be_ctx,
     205             :                                   const char *domain)
     206             : {
     207             :     struct be_req *be_req;
     208             :     struct be_req *next_be_req;
     209             : 
     210           1 :     DEBUG(SSSDBG_TRACE_FUNC, "Terminating requests for domain [%s]\n",
     211             :                               domain);
     212             : 
     213           1 :     if (domain == NULL) {
     214           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "BUG: domain is NULL\n");
     215           0 :         return;
     216             :     }
     217             : 
     218           1 :     be_req = be_ctx->active_requests;
     219           2 :     while (be_req) {
     220             :         /* save pointer to next request in case be_req will be freed */
     221           0 :         next_be_req = be_req->next;
     222           0 :         if (strcmp(domain, be_req->domain->name) == 0) {
     223           0 :             be_req_terminate(be_req, DP_ERR_FATAL, ERR_DOMAIN_NOT_FOUND,
     224             :                              sss_strerror(ERR_DOMAIN_NOT_FOUND));
     225             :         }
     226           0 :         be_req = next_be_req;
     227             :     }
     228             : }
     229             : 
     230             : struct be_async_req {
     231             :     be_req_fn_t fn;
     232             :     struct be_req *req;
     233             : };
     234             : 
     235           0 : static void be_async_req_handler(struct tevent_context *ev,
     236             :                                  struct tevent_timer *te,
     237             :                                  struct timeval tv, void *pvt)
     238             : {
     239             :     struct be_async_req *async_req;
     240             : 
     241           0 :     async_req = talloc_get_type(pvt, struct be_async_req);
     242             : 
     243           0 :     async_req->fn(async_req->req);
     244           0 : }
     245             : 
     246             : struct be_spy {
     247             :     TALLOC_CTX *freectx;
     248             :     struct be_spy *double_agent;
     249             : };
     250             : 
     251           0 : static int be_spy_destructor(struct be_spy *spy)
     252             : {
     253             :     /* If there's a double_agent, set its
     254             :      * freectx to NULL so that we don't
     255             :      * try to loop. When that spy fires,
     256             :      * it will just be a no-op.
     257             :      */
     258           0 :     spy->double_agent->freectx = NULL;
     259           0 :     talloc_zfree(spy->freectx);
     260           0 :     return 0;
     261             : }
     262             : 
     263           0 : static errno_t be_spy_create(TALLOC_CTX *mem_ctx, struct be_req *be_req)
     264             : {
     265             :     errno_t ret;
     266           0 :     struct be_spy *cli_spy = NULL;
     267           0 :     struct be_spy *req_spy = NULL;
     268             : 
     269             :     /* Attach a spy for the be_client so that if it dies,
     270             :      * we can free the be_req automatically.
     271             :      */
     272           0 :     cli_spy = talloc_zero(be_req->becli, struct be_spy);
     273           0 :     if (!cli_spy) {
     274           0 :         ret = ENOMEM;
     275           0 :         goto done;
     276             :     }
     277           0 :     cli_spy->freectx = be_req;
     278             : 
     279             :     /* Also create a spy on the be_req so that we
     280             :      * can free the other spy when the be_req
     281             :      * completes successfully.
     282             :      */
     283           0 :     req_spy = talloc_zero(be_req, struct be_spy);
     284           0 :     if (!req_spy) {
     285           0 :         ret = ENOMEM;
     286           0 :         goto done;
     287             :     }
     288           0 :     req_spy->freectx = cli_spy;
     289             : 
     290             :     /* Create paired spy links to prevent loops */
     291           0 :     cli_spy->double_agent = req_spy;
     292           0 :     req_spy->double_agent = cli_spy;
     293             : 
     294             :     /* Now create the destructors that will actually free
     295             :      * the opposing spies.
     296             :      */
     297           0 :     talloc_set_destructor(cli_spy, be_spy_destructor);
     298           0 :     talloc_set_destructor(req_spy, be_spy_destructor);
     299             : 
     300             : 
     301             :     /* Now steal the be_req onto the mem_ctx so that it
     302             :      * will be guaranteed that this data will be
     303             :      * available for the full duration of execution.
     304             :      */
     305           0 :     talloc_steal(mem_ctx, be_req);
     306             : 
     307           0 :     ret = EOK;
     308             : done:
     309           0 :     if (ret != EOK) {
     310           0 :         talloc_free(cli_spy);
     311           0 :         talloc_free(req_spy);
     312             :     }
     313           0 :     return ret;
     314             : }
     315             : 
     316             : /* This function alters the memory hierarchy of the be_req
     317             :  * to ensure memory safety during shutdown. It creates a
     318             :  * spy on the be_cli object so that it will free the be_req
     319             :  * if the client is freed.
     320             :  *
     321             :  * It is generally allocated atop the private data context
     322             :  * for the appropriate back-end against which it is being
     323             :  * filed.
     324             :  */
     325           0 : static errno_t be_file_request(TALLOC_CTX *mem_ctx,
     326             :                                struct be_req *be_req,
     327             :                                be_req_fn_t fn)
     328             : {
     329             :     errno_t ret;
     330             :     struct be_async_req *areq;
     331             :     struct tevent_timer *te;
     332             :     struct timeval tv;
     333             : 
     334           0 :     if (!fn || !be_req) return EINVAL;
     335             : 
     336           0 :     ret = be_spy_create(mem_ctx, be_req);
     337           0 :     if (ret != EOK) return ret;
     338             : 
     339           0 :     areq = talloc(be_req, struct be_async_req);
     340           0 :     if (!areq) {
     341           0 :         return ENOMEM;
     342             :     }
     343           0 :     areq->fn = fn;
     344           0 :     areq->req = be_req;
     345             : 
     346             :     /* fire immediately */
     347           0 :     tv.tv_sec = 0;
     348           0 :     tv.tv_usec = 0;
     349             : 
     350           0 :     te = tevent_add_timer(be_req->be_ctx->ev, be_req,
     351             :                           tv, be_async_req_handler, areq);
     352           0 :     if (te == NULL) {
     353           0 :         return EIO;
     354             :     }
     355             : 
     356           0 :     return EOK;
     357             : }
     358             : 
     359           0 : static errno_t be_queue_request(TALLOC_CTX *queue_mem_ctx,
     360             :                                 struct bet_queue_item **req_queue,
     361             :                                 TALLOC_CTX *req_mem_ctx,
     362             :                                 struct be_req *be_req,
     363             :                                 be_req_fn_t fn)
     364             : {
     365             :     struct bet_queue_item *item;
     366             :     int ret;
     367             : 
     368           0 :     if (*req_queue == NULL) {
     369           0 :         DEBUG(SSSDBG_TRACE_ALL, "Queue is empty, " \
     370             :                                  "running request immediately.\n");
     371           0 :         ret = be_file_request(req_mem_ctx, be_req, fn);
     372           0 :         if (ret != EOK) {
     373           0 :             DEBUG(SSSDBG_OP_FAILURE, "be_file_request failed.\n");
     374           0 :             return ret;
     375             :         }
     376             :     }
     377             : 
     378           0 :     item = talloc_zero(queue_mem_ctx, struct bet_queue_item);
     379           0 :     if (item == NULL) {
     380           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed, cannot add item to " \
     381             :                                   "request queue.\n");
     382             :     } else {
     383           0 :         DEBUG(SSSDBG_TRACE_ALL, "Adding request to queue.\n");
     384           0 :         item->mem_ctx = req_mem_ctx;
     385           0 :         item->be_req = be_req;
     386           0 :         item->fn = fn;
     387             : 
     388           0 :         DLIST_ADD_END(*req_queue, item, struct bet_queue_item *);
     389             :     }
     390             : 
     391           0 :     return EOK;
     392             : }
     393             : 
     394           0 : static void be_queue_next_request(struct be_req *be_req, enum bet_type type)
     395             : {
     396             :     struct bet_queue_item *item;
     397           0 :     struct bet_queue_item *current = NULL;
     398             :     struct bet_queue_item **req_queue;
     399             :     struct sbus_request *dbus_req;
     400             :     int ret;
     401             :     uint16_t err_maj;
     402             :     uint32_t err_min;
     403           0 :     const char *err_msg = "Cannot file back end request";
     404           0 :     struct be_req *next_be_req = NULL;
     405             : 
     406           0 :     req_queue = &be_req->becli->bectx->bet_info[type].req_queue;
     407             : 
     408           0 :     if (*req_queue == NULL) {
     409           0 :         DEBUG(SSSDBG_TRACE_ALL, "Queue is empty, nothing to do.\n");
     410           0 :         return;
     411             :     }
     412             : 
     413           0 :     DLIST_FOR_EACH(item, *req_queue) {
     414           0 :         if (item->be_req == be_req) {
     415           0 :             current = item;
     416           0 :             break;
     417             :         }
     418             :     }
     419             : 
     420           0 :     if (current != NULL) {
     421           0 :         DLIST_REMOVE(*req_queue, current);
     422             :     }
     423             : 
     424           0 :     if (*req_queue == NULL) {
     425           0 :         DEBUG(SSSDBG_TRACE_ALL, "Request queue is empty.\n");
     426           0 :         return;
     427             :     }
     428             : 
     429           0 :     next_be_req = (*req_queue)->be_req;
     430             : 
     431           0 :     ret = be_file_request((*req_queue)->mem_ctx, next_be_req, (*req_queue)->fn);
     432           0 :     if (ret == EOK) {
     433           0 :         DEBUG(SSSDBG_TRACE_ALL, "Queued request filed successfully.\n");
     434           0 :         return;
     435             :     }
     436             : 
     437           0 :     DEBUG(SSSDBG_OP_FAILURE, "be_file_request failed.\n");
     438             : 
     439           0 :     be_queue_next_request(next_be_req, type);
     440             : 
     441           0 :     dbus_req = (struct sbus_request *) next_be_req->pvt;
     442             : 
     443           0 :     if (dbus_req) {
     444             :         /* Return a reply if one was requested
     445             :          * There may not be one if this request began
     446             :          * while we were offline
     447             :          */
     448           0 :         err_maj = DP_ERR_FATAL;
     449           0 :         err_min = ret;
     450             : 
     451           0 :         sbus_request_return_and_finish(dbus_req,
     452             :                                        DBUS_TYPE_UINT16, &err_maj,
     453             :                                        DBUS_TYPE_UINT32, &err_min,
     454             :                                        DBUS_TYPE_STRING, &err_msg,
     455             :                                        DBUS_TYPE_INVALID);
     456             :     }
     457             : 
     458           0 :     talloc_free(next_be_req);
     459             : }
     460             : 
     461           4 : bool be_is_offline(struct be_ctx *ctx)
     462             : {
     463           4 :     return ctx->offstat.offline;
     464             : }
     465             : 
     466             : static void check_if_online(struct be_ctx *ctx);
     467             : 
     468             : static errno_t
     469           0 : try_to_go_online(TALLOC_CTX *mem_ctx,
     470             :                  struct tevent_context *ev,
     471             :                  struct be_ctx *be_ctx,
     472             :                  struct be_ptask *be_ptask,
     473             :                  void *be_ctx_void)
     474             : {
     475           0 :     struct be_ctx *ctx = (struct be_ctx*) be_ctx_void;
     476             : 
     477           0 :     check_if_online(ctx);
     478           0 :     return EOK;
     479             : }
     480             : 
     481           4 : static int get_offline_timeout(struct be_ctx *ctx)
     482             : {
     483             :     errno_t ret;
     484             :     int offline_timeout;
     485             : 
     486           4 :     ret = confdb_get_int(ctx->cdb, ctx->conf_path,
     487             :                          CONFDB_DOMAIN_OFFLINE_TIMEOUT, 60,
     488             :                          &offline_timeout);
     489           4 :     if (ret != EOK) {
     490           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     491             :               "Failed to get offline_timeout from confdb. "
     492             :               "Will use 60 seconds.\n");
     493           0 :         offline_timeout = 60;
     494             :     }
     495             : 
     496           4 :     return offline_timeout;
     497             : }
     498             : 
     499           1 : void be_mark_offline(struct be_ctx *ctx)
     500             : {
     501             :     int offline_timeout;
     502             :     errno_t ret;
     503             : 
     504           1 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Going offline!\n");
     505             : 
     506           1 :     ctx->offstat.went_offline = time(NULL);
     507           1 :     ctx->offstat.offline = true;
     508           1 :     ctx->run_online_cb = true;
     509             : 
     510           1 :     if (ctx->check_if_online_ptask == NULL) {
     511             :         /* This is the first time we go offline - create a periodic task
     512             :          * to check if we can switch to online. */
     513           1 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Initialize check_if_online_ptask.\n");
     514             : 
     515           1 :         offline_timeout = get_offline_timeout(ctx);
     516             : 
     517           1 :         ret = be_ptask_create_sync(ctx, ctx,
     518             :                                    offline_timeout, offline_timeout,
     519             :                                    offline_timeout, 30, offline_timeout,
     520             :                                    BE_PTASK_OFFLINE_EXECUTE,
     521             :                                    3600 /* max_backoff */,
     522             :                                    try_to_go_online,
     523             :                                    ctx, "Check if online (periodic)",
     524             :                                    &ctx->check_if_online_ptask);
     525           1 :         if (ret != EOK) {
     526           1 :             DEBUG(SSSDBG_FATAL_FAILURE,
     527             :                   "be_ptask_create_sync failed [%d]: %s\n",
     528             :                   ret, sss_strerror(ret));
     529             :         }
     530             :     } else {
     531             :         /* Periodic task was already created. Just enable it. */
     532           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Enable check_if_online_ptask.\n");
     533           0 :         be_ptask_enable(ctx->check_if_online_ptask);
     534             :     }
     535             : 
     536           1 :     be_run_offline_cb(ctx);
     537           1 : }
     538             : 
     539           1 : static void be_subdom_reset_status(struct tevent_context *ev,
     540             :                                   struct tevent_timer *te,
     541             :                                   struct timeval current_time,
     542             :                                   void *pvt)
     543             : {
     544           1 :     struct sss_domain_info *subdom = talloc_get_type(pvt,
     545             :                                                      struct sss_domain_info);
     546             : 
     547           1 :     DEBUG(SSSDBG_TRACE_LIBS, "Resetting subdomain %s\n", subdom->name);
     548           1 :     subdom->state = DOM_ACTIVE;
     549           1 : }
     550             : 
     551           3 : static void be_mark_subdom_offline(struct sss_domain_info *subdom,
     552             :                                    struct be_ctx *be_ctx)
     553             : {
     554             :     struct timeval tv;
     555           3 :     struct tevent_timer *timeout = NULL;
     556             :     int reset_status_timeout;
     557             : 
     558           3 :     reset_status_timeout = get_offline_timeout(be_ctx);
     559           3 :     tv = tevent_timeval_current_ofs(reset_status_timeout, 0);
     560             : 
     561           3 :     switch (subdom->state) {
     562             :     case DOM_DISABLED:
     563           1 :         DEBUG(SSSDBG_MINOR_FAILURE, "Won't touch disabled subdomain\n");
     564           3 :         return;
     565             :     case DOM_INACTIVE:
     566           1 :         DEBUG(SSSDBG_TRACE_ALL, "Subdomain already inactive\n");
     567           1 :         return;
     568             :     case DOM_ACTIVE:
     569           1 :         DEBUG(SSSDBG_TRACE_LIBS,
     570             :               "Marking subdomain %s as inactive\n", subdom->name);
     571           1 :         break;
     572             :     }
     573             : 
     574           1 :     timeout = tevent_add_timer(be_ctx->ev, be_ctx, tv,
     575             :                                be_subdom_reset_status, subdom);
     576           1 :     if (timeout == NULL) {
     577           0 :         DEBUG(SSSDBG_OP_FAILURE, "Cannot create timer\n");
     578           0 :         return;
     579             :     }
     580             : 
     581           1 :     subdom->state = DOM_INACTIVE;
     582             : }
     583             : 
     584           4 : void be_mark_dom_offline(struct sss_domain_info *dom, struct be_ctx *ctx)
     585             : {
     586           4 :     if (IS_SUBDOMAIN(dom) == false) {
     587           1 :         DEBUG(SSSDBG_TRACE_LIBS, "Marking back end offline\n");
     588           1 :         be_mark_offline(ctx);
     589             :     } else {
     590           3 :         DEBUG(SSSDBG_TRACE_LIBS, "Marking subdomain %s offline\n", dom->name);
     591           3 :         be_mark_subdom_offline(dom, ctx);
     592             :     }
     593           4 : }
     594             : 
     595           0 : static void reactivate_subdoms(struct sss_domain_info *head)
     596             : {
     597             :     struct sss_domain_info *dom;
     598             : 
     599           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Resetting all subdomains");
     600             : 
     601           0 :     for (dom = head; dom; dom = get_next_domain(dom, true)) {
     602           0 :         if (sss_domain_get_state(dom) == DOM_INACTIVE) {
     603           0 :             sss_domain_set_state(dom, DOM_ACTIVE);
     604             :         }
     605             :     }
     606           0 : }
     607             : 
     608           0 : static void be_reset_offline(struct be_ctx *ctx)
     609             : {
     610           0 :     ctx->offstat.went_offline = 0;
     611           0 :     ctx->offstat.offline = false;
     612             : 
     613           0 :     reactivate_subdoms(ctx->domain);
     614             : 
     615           0 :     be_ptask_disable(ctx->check_if_online_ptask);
     616           0 :     be_run_online_cb(ctx);
     617           0 : }
     618             : 
     619           0 : static char *dp_pam_err_to_string(TALLOC_CTX *memctx, int dp_err_type, int errnum)
     620             : {
     621           0 :     switch (dp_err_type) {
     622             :     case DP_ERR_OK:
     623           0 :         return talloc_asprintf(memctx, "Success (%s)",
     624             :                                pam_strerror(NULL, errnum));
     625             :         break;
     626             : 
     627             :     case DP_ERR_OFFLINE:
     628           0 :         return talloc_asprintf(memctx,
     629             :                                "Provider is Offline (%s)",
     630             :                                pam_strerror(NULL, errnum));
     631             :         break;
     632             : 
     633             :     case DP_ERR_TIMEOUT:
     634           0 :         return talloc_asprintf(memctx,
     635             :                                "Request timed out (%s)",
     636             :                                pam_strerror(NULL, errnum));
     637             :         break;
     638             : 
     639             :     case DP_ERR_FATAL:
     640             :     default:
     641           0 :         return talloc_asprintf(memctx,
     642             :                                "Internal Error (%s)",
     643             :                                pam_strerror(NULL, errnum));
     644             :         break;
     645             :     }
     646             : 
     647             :     return NULL;
     648             : }
     649             : 
     650           0 : static void get_subdomains_callback(struct be_req *req,
     651             :                                     int dp_err_type,
     652             :                                     int errnum,
     653             :                                     const char *errstr)
     654             : {
     655             :     struct sbus_request *dbus_req;
     656           0 :     dbus_uint16_t err_maj = 0;
     657           0 :     dbus_uint32_t err_min = 0;
     658           0 :     const char *err_msg = NULL;
     659             : 
     660           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Backend returned: (%d, %d, %s) [%s]\n",
     661             :               dp_err_type, errnum, errstr?errstr:"<NULL>",
     662             :               dp_pam_err_to_string(req, dp_err_type, errnum));
     663             : 
     664           0 :     be_queue_next_request(req, BET_SUBDOMAINS);
     665             : 
     666           0 :     dbus_req = (struct sbus_request *)req->pvt;
     667             : 
     668           0 :     if (dbus_req) {
     669             :         /* Return a reply if one was requested
     670             :          * There may not be one if this request began
     671             :          * while we were offline
     672             :          */
     673           0 :         err_maj = dp_err_type;
     674           0 :         err_min = errnum;
     675           0 :         if (errstr) {
     676           0 :             err_msg = errstr;
     677             :         } else {
     678           0 :             err_msg = dp_pam_err_to_string(req, dp_err_type, errnum);
     679             :         }
     680           0 :         if (!err_msg) {
     681           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     682             :                   "Failed to set err_msg, Out of memory?\n");
     683           0 :             err_msg = "OOM";
     684             :         }
     685             : 
     686           0 :         sbus_request_return_and_finish(dbus_req,
     687             :                                        DBUS_TYPE_UINT16, &err_maj,
     688             :                                        DBUS_TYPE_UINT32, &err_min,
     689             :                                        DBUS_TYPE_STRING, &err_msg,
     690             :                                        DBUS_TYPE_INVALID);
     691             :     }
     692             : 
     693           0 :     talloc_free(req);
     694           0 : }
     695             : 
     696           0 : static int be_get_subdomains(struct sbus_request *dbus_req, void *user_data)
     697             : {
     698             :     struct be_subdom_req *req;
     699           0 :     struct be_req *be_req = NULL;
     700             :     struct be_client *becli;
     701             :     char *domain_hint;
     702             :     dbus_uint16_t err_maj;
     703             :     dbus_uint32_t err_min;
     704             :     const char *err_msg;
     705             :     int ret;
     706             : 
     707           0 :     becli = talloc_get_type(user_data, struct be_client);
     708           0 :     if (!becli) return EINVAL;
     709             : 
     710           0 :     if (!sbus_request_parse_or_finish(dbus_req,
     711             :                                       DBUS_TYPE_STRING, &domain_hint,
     712             :                                       DBUS_TYPE_INVALID))
     713           0 :         return EOK; /* handled */
     714             : 
     715             :     /* return an error if corresponding backend target is not configured */
     716           0 :     if (becli->bectx->bet_info[BET_SUBDOMAINS].bet_ops == NULL) {
     717           0 :         DEBUG(SSSDBG_TRACE_INTERNAL, "Undefined backend target.\n");
     718           0 :         err_maj = DP_ERR_FATAL;
     719           0 :         err_min = ENODEV;
     720           0 :         err_msg = "Subdomains back end target is not configured";
     721           0 :         goto immediate;
     722             :     }
     723             : 
     724           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Got get subdomains [%s]\n",
     725             :                              domain_hint == NULL ? "no hint": domain_hint );
     726             : 
     727             :     /* If we are offline return immediately
     728             :      */
     729           0 :     if (becli->bectx->offstat.offline) {
     730           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Cannot proceed, provider is offline.\n");
     731           0 :         err_maj = DP_ERR_OFFLINE;
     732           0 :         err_min = EAGAIN;
     733           0 :         err_msg = "Provider is offline";
     734           0 :         goto immediate;
     735             :     }
     736             : 
     737             :     /* process request */
     738             : 
     739           0 :     be_req = be_req_create(becli, becli, becli->bectx,
     740             :                            get_subdomains_callback, dbus_req);
     741           0 :     if (!be_req) {
     742           0 :         err_maj = DP_ERR_FATAL;
     743           0 :         err_min = ENOMEM;
     744           0 :         err_msg = "Out of memory";
     745           0 :         goto immediate;
     746             :     }
     747             : 
     748           0 :     req = talloc(be_req, struct be_subdom_req);
     749           0 :     if (!req) {
     750           0 :         err_maj = DP_ERR_FATAL;
     751           0 :         err_min = ENOMEM;
     752           0 :         err_msg = "Out of memory";
     753           0 :         goto immediate;
     754             :     }
     755           0 :     req->domain_hint = talloc_strdup(req, domain_hint);
     756           0 :     if (!req->domain_hint) {
     757           0 :         err_maj = DP_ERR_FATAL;
     758           0 :         err_min = ENOMEM;
     759           0 :         err_msg = "Out of memory";
     760           0 :         goto immediate;
     761             :     }
     762             : 
     763           0 :     be_req->req_data = req;
     764             : 
     765           0 :     ret = be_queue_request(becli->bectx,
     766           0 :                            &becli->bectx->bet_info[BET_SUBDOMAINS].req_queue,
     767           0 :                            becli->bectx,
     768             :                            be_req,
     769           0 :                            becli->bectx->bet_info[BET_SUBDOMAINS].bet_ops->handler);
     770           0 :     if (ret != EOK) {
     771           0 :         err_maj = DP_ERR_FATAL;
     772           0 :         err_min = ret;
     773           0 :         err_msg = "Cannot file back end request";
     774           0 :         goto immediate;
     775             :     }
     776             : 
     777           0 :     return EOK;
     778             : 
     779             : immediate:
     780           0 :     if (be_req) {
     781           0 :         talloc_free(be_req);
     782             :     }
     783             : 
     784             :     /* send reply back */
     785           0 :     sbus_request_return_and_finish(dbus_req,
     786             :                                    DBUS_TYPE_UINT16, &err_maj,
     787             :                                    DBUS_TYPE_UINT32, &err_min,
     788             :                                    DBUS_TYPE_STRING, &err_msg,
     789             :                                    DBUS_TYPE_INVALID);
     790             : 
     791           0 :     if (!(err_maj == DP_ERR_FATAL && err_min == ENODEV)) {
     792           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Request processed. Returned %d,%d,%s\n",
     793             :                 err_maj, err_min, err_msg);
     794             :     }
     795             : 
     796           0 :     return EOK;
     797             : }
     798             : 
     799           0 : static void acctinfo_callback(struct be_req *req,
     800             :                               int dp_err_type,
     801             :                               int errnum,
     802             :                               const char *errstr)
     803             : {
     804             :     struct sbus_request *dbus_req;
     805           0 :     dbus_uint16_t err_maj = 0;
     806           0 :     dbus_uint32_t err_min = 0;
     807           0 :     const char *err_msg = NULL;
     808             : 
     809           0 :     dbus_req = (struct sbus_request *)req->pvt;
     810             : 
     811           0 :     if (dbus_req) {
     812             :         /* Return a reply if one was requested
     813             :          * There may not be one if this request began
     814             :          * while we were offline
     815             :          */
     816             : 
     817           0 :         err_maj = dp_err_type;
     818           0 :         err_min = errnum;
     819           0 :         if (errstr) {
     820           0 :             err_msg = errstr;
     821             :         } else {
     822           0 :             err_msg = dp_pam_err_to_string(req, dp_err_type, errnum);
     823             :         }
     824           0 :         if (!err_msg) {
     825           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
     826             :                   "Failed to set err_msg, Out of memory?\n");
     827           0 :             err_msg = "OOM";
     828             :         }
     829             : 
     830           0 :         sbus_request_return_and_finish(dbus_req,
     831             :                                        DBUS_TYPE_UINT16, &err_maj,
     832             :                                        DBUS_TYPE_UINT32, &err_min,
     833             :                                        DBUS_TYPE_STRING, &err_msg,
     834             :                                        DBUS_TYPE_INVALID);
     835             : 
     836           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "Request processed. Returned %d,%d,%s\n",
     837             :                   err_maj, err_min, err_msg);
     838             :     }
     839             : 
     840             :     /* finally free the request */
     841           0 :     talloc_free(req);
     842           0 : }
     843             : 
     844             : struct be_initgr_prereq {
     845             :     char *user;
     846             :     char *domain;
     847             :     uint32_t gnum;
     848             :     uint32_t *groups;
     849             : 
     850             :     void *orig_pvt_data;
     851             :     int orig_dp_err_type;
     852             :     int orig_errnum;
     853             :     const char *orig_errstr;
     854             : };
     855             : 
     856           0 : static void acctinfo_callback_initgr_wrap(struct be_req *be_req)
     857             : {
     858           0 :     struct be_initgr_prereq *pr = talloc_get_type(be_req->pvt,
     859             :                                                   struct be_initgr_prereq);
     860             : 
     861           0 :     be_req->pvt = pr->orig_pvt_data;
     862           0 :     acctinfo_callback(be_req, pr->orig_dp_err_type,
     863             :                       pr->orig_errnum, pr->orig_errstr);
     864           0 : }
     865             : 
     866           0 : static void acctinfo_callback_initgr_sbus(DBusPendingCall *pending, void *ptr)
     867             : {
     868           0 :     struct be_req *be_req = talloc_get_type(ptr, struct be_req);
     869             : 
     870           0 :     dbus_pending_call_unref(pending);
     871             : 
     872           0 :     acctinfo_callback_initgr_wrap(be_req);
     873           0 : }
     874             : 
     875           0 : static void acctinfo_initgroups_callback(struct be_req *be_req,
     876             :                                          int dp_err_type,
     877             :                                          int errnum,
     878             :                                          const char *errstr)
     879             : {
     880           0 :     struct be_initgr_prereq *pr = talloc_get_type(be_req->pvt,
     881             :                                                   struct be_initgr_prereq);
     882           0 :     DBusMessage *msg = NULL;
     883             :     dbus_bool_t dbret;
     884             :     int num;
     885             :     int ret;
     886             : 
     887           0 :     pr->orig_dp_err_type = dp_err_type;
     888           0 :     pr->orig_errnum = errnum;
     889           0 :     pr->orig_errstr = errstr;
     890             : 
     891           0 :     if (!be_req->be_ctx->nss_cli || !be_req->be_ctx->nss_cli->conn) {
     892           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "NSS Service not conected\n");
     893           0 :         ret = EACCES;
     894           0 :         goto done;
     895             :     }
     896             : 
     897             :     /* Set up null request */
     898           0 :     msg = dbus_message_new_method_call(NULL,
     899             :                                        DP_PATH,
     900             :                                        DATA_PROVIDER_REV_IFACE,
     901             :                                        DATA_PROVIDER_REV_IFACE_INITGRCHECK);
     902           0 :     if (!msg) {
     903           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory?!\n");
     904           0 :         ret = ENOMEM;
     905           0 :         goto done;
     906             :     }
     907             : 
     908           0 :     num = pr->gnum;
     909           0 :     dbret = dbus_message_append_args(msg,
     910             :                                      DBUS_TYPE_STRING, &pr->user,
     911             :                                      DBUS_TYPE_STRING, &pr->domain,
     912             :                                      DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
     913             :                                      &pr->groups, num,
     914             :                                      DBUS_TYPE_INVALID);
     915           0 :     if (!dbret) {
     916           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory?!\n");
     917           0 :         ret = ENOMEM;
     918           0 :         goto done;
     919             :     }
     920             : 
     921             :     /* ping the NSS service, no reply expected */
     922           0 :     ret = sbus_conn_send(be_req->be_ctx->nss_cli->conn, msg, -1,
     923             :                          acctinfo_callback_initgr_sbus, be_req, NULL);
     924           0 :     if (ret != EOK) {
     925           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     926             :               "Error contacting NSS responder: %d [%s]\n",
     927             :                ret, strerror(ret));
     928             :     }
     929             : 
     930             : done:
     931           0 :     if (msg) {
     932           0 :         dbus_message_unref(msg);
     933             :     }
     934           0 :     if (ret != EOK) {
     935             :         /* return immediately if we cannot contact nss provider */
     936           0 :         acctinfo_callback_initgr_wrap(be_req);
     937             :     }
     938           0 : }
     939             : 
     940           0 : static errno_t be_initgroups_prereq(struct be_req *be_req)
     941             : {
     942           0 :     struct be_acct_req *ar = talloc_get_type(be_req_get_data(be_req),
     943             :                                              struct be_acct_req);
     944             :     struct be_initgr_prereq *pr;
     945             :     struct ldb_result *res;
     946             :     errno_t ret;
     947             :     const char *tmpstr;
     948             :     int i;
     949             : 
     950           0 :     ret = sysdb_initgroups(be_req, be_req->be_ctx->domain, ar->filter_value,
     951             :                            &res);
     952           0 :     if (ret && ret != ENOENT) {
     953           0 :         return ret;
     954             :     }
     955             :     /* if the user is completely missing there is no need to contact NSS,
     956             :      * it would be a noop */
     957           0 :     if (ret == ENOENT || res->count == 0) {
     958             :         /* yet unknown, ignore */
     959           0 :         return EOK;
     960             :     }
     961             : 
     962           0 :     pr = talloc(be_req, struct be_initgr_prereq);
     963           0 :     if (!pr) {
     964           0 :         return ENOMEM;
     965             :     }
     966           0 :     pr->groups = talloc_array(pr, gid_t, res->count);
     967           0 :     if (!pr->groups) {
     968           0 :         return ENOMEM;
     969             :     }
     970           0 :     tmpstr = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
     971           0 :     if (!tmpstr) {
     972           0 :         return EINVAL;
     973             :     }
     974           0 :     pr->user = talloc_strdup(pr, tmpstr);
     975           0 :     if (!pr->user) {
     976           0 :         return ENOMEM;
     977             :     }
     978           0 :     pr->domain = talloc_strdup(pr, be_req->be_ctx->domain->name);
     979           0 :     if (!pr->domain) {
     980           0 :         return ENOMEM;
     981             :     }
     982             :     /* The first GID is the primary so it might be duplicated
     983             :      * later in the list */
     984           0 :     for (pr->gnum = 0, i = 0; i < res->count; i++) {
     985           0 :         pr->groups[pr->gnum] = ldb_msg_find_attr_as_uint(res->msgs[i],
     986             :                                                          SYSDB_GIDNUM, 0);
     987             :         /* if 0 it may be a non-posix group, so we skip it */
     988           0 :         if (pr->groups[pr->gnum] != 0) {
     989           0 :             pr->gnum++;
     990             :         }
     991             :     }
     992             : 
     993           0 :     talloc_zfree(res);
     994             : 
     995           0 :     pr->orig_pvt_data = be_req->pvt;
     996           0 :     be_req->pvt = pr;
     997           0 :     be_req->fn = acctinfo_initgroups_callback;
     998             : 
     999           0 :     return EOK;
    1000             : }
    1001             : 
    1002             : static errno_t
    1003           0 : be_file_account_request(struct be_req *be_req, struct be_acct_req *ar)
    1004             : {
    1005             :     errno_t ret;
    1006           0 :     struct be_ctx *be_ctx = be_req->be_ctx;
    1007             : 
    1008           0 :     be_req->req_data = ar;
    1009             : 
    1010             :     /* see if we need a pre request call, only done for initgroups for now */
    1011           0 :     if ((ar->entry_type & 0xFF) == BE_REQ_INITGROUPS) {
    1012           0 :         ret = be_initgroups_prereq(be_req);
    1013           0 :         if (ret) {
    1014           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Prerequest failed\n");
    1015           0 :             return ret;
    1016             :         }
    1017             :     }
    1018             : 
    1019             :     /* process request */
    1020           0 :     ret = be_file_request(be_ctx, be_req,
    1021           0 :                           be_ctx->bet_info[BET_ID].bet_ops->handler);
    1022           0 :     if (ret != EOK) {
    1023           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to file request\n");
    1024           0 :         return ret;
    1025             :     }
    1026             : 
    1027           0 :     return EOK;
    1028             : }
    1029             : 
    1030             : static errno_t
    1031           0 : split_name_extended(TALLOC_CTX *mem_ctx,
    1032             :                     const char *filter,
    1033             :                     char **name,
    1034             :                     char **extended)
    1035             : {
    1036             :     char *p;
    1037             : 
    1038           0 :     *name = talloc_strdup(mem_ctx, filter);
    1039           0 :     if (!*name) {
    1040           0 :         return ENOENT;
    1041             :     }
    1042             : 
    1043           0 :     p = strchr(*name, ':');
    1044           0 :     if (p) {
    1045             :         /* Extended info included */
    1046           0 :         *p = '\0';
    1047             : 
    1048           0 :         *extended = p + 1;
    1049             :     } else {
    1050           0 :         *extended = NULL;
    1051             :     }
    1052             : 
    1053           0 :     return EOK;
    1054             : }
    1055             : 
    1056             : static void
    1057             : be_get_account_info_done(struct be_req *be_req,
    1058             :                          int dp_err, int dp_ret,
    1059             :                          const char *errstr);
    1060             : 
    1061             : struct be_get_account_info_state {
    1062             :     int err_maj;
    1063             :     int err_min;
    1064             :     const char *err_msg;
    1065             : };
    1066             : 
    1067             : struct tevent_req *
    1068           0 : be_get_account_info_send(TALLOC_CTX *mem_ctx,
    1069             :                          struct tevent_context *ev,
    1070             :                          struct be_client *becli,
    1071             :                          struct be_ctx *be_ctx,
    1072             :                          struct be_acct_req *ar)
    1073             : {
    1074             :     struct tevent_req *req;
    1075             :     struct be_get_account_info_state *state;
    1076             :     struct be_req *be_req;
    1077             :     errno_t ret;
    1078             : 
    1079           0 :     req = tevent_req_create(mem_ctx, &state,
    1080             :                             struct be_get_account_info_state);
    1081           0 :     if (!req) return NULL;
    1082             : 
    1083           0 :     be_req = be_req_create(state, becli, be_ctx,
    1084             :                            be_get_account_info_done, req);
    1085           0 :     if (!be_req) {
    1086           0 :         ret = ENOMEM;
    1087           0 :         goto done;
    1088             :     }
    1089             : 
    1090           0 :     ret = be_req_set_domain(be_req, ar->domain);
    1091           0 :     if (ret != EOK) {
    1092           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set request domain [%d]: %s\n",
    1093             :                                     ret, sss_strerror(ret));
    1094           0 :         goto done;
    1095             :     }
    1096             : 
    1097           0 :     ret = be_file_account_request(be_req, ar);
    1098           0 :     if (ret != EOK) {
    1099           0 :         goto done;
    1100             :     }
    1101             : 
    1102           0 :     return req;
    1103             : 
    1104             : done:
    1105           0 :     tevent_req_error(req, ret);
    1106           0 :     tevent_req_post(req, ev);
    1107           0 :     return req;
    1108             : }
    1109             : 
    1110             : static void
    1111           0 : be_get_account_info_done(struct be_req *be_req,
    1112             :                          int dp_err, int dp_ret,
    1113             :                          const char *errstr)
    1114             : {
    1115             :     struct tevent_req *req;
    1116             :     struct be_get_account_info_state *state;
    1117             : 
    1118           0 :     req = talloc_get_type(be_req->pvt, struct tevent_req);
    1119           0 :     state = tevent_req_data(req, struct be_get_account_info_state);
    1120             : 
    1121           0 :     state->err_maj = dp_err;
    1122           0 :     state->err_min = dp_ret;
    1123           0 :     if (errstr) {
    1124           0 :         state->err_msg = talloc_strdup(state, errstr);
    1125           0 :         if (state->err_msg == NULL) {
    1126           0 :             talloc_free(be_req);
    1127           0 :             tevent_req_error(req, ENOMEM);
    1128           0 :             return;
    1129             :         }
    1130             :     }
    1131             : 
    1132           0 :     talloc_free(be_req);
    1133           0 :     tevent_req_done(req);
    1134             : }
    1135             : 
    1136           0 : errno_t be_get_account_info_recv(struct tevent_req *req,
    1137             :                                  TALLOC_CTX *mem_ctx,
    1138             :                                  int *_err_maj,
    1139             :                                  int *_err_min,
    1140             :                                  const char **_err_msg)
    1141             : {
    1142             :     struct be_get_account_info_state *state;
    1143             : 
    1144           0 :     state = tevent_req_data(req, struct be_get_account_info_state);
    1145             : 
    1146           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
    1147             : 
    1148           0 :     if (_err_maj) {
    1149           0 :         *_err_maj = state->err_maj;
    1150             :     }
    1151             : 
    1152           0 :     if (_err_min) {
    1153           0 :         *_err_min = state->err_min;
    1154             :     }
    1155             : 
    1156           0 :     if (_err_msg) {
    1157           0 :         *_err_msg = talloc_steal(mem_ctx, state->err_msg);
    1158             :     }
    1159             : 
    1160           0 :     return EOK;
    1161             : }
    1162             : 
    1163           0 : static int be_get_account_info(struct sbus_request *dbus_req, void *user_data)
    1164             : {
    1165             :     struct be_acct_req *req;
    1166             :     struct be_req *be_req;
    1167             :     struct be_client *becli;
    1168             :     uint32_t type;
    1169             :     char *filter;
    1170             :     char *domain;
    1171             :     uint32_t attr_type;
    1172             :     int ret;
    1173             :     dbus_uint16_t err_maj;
    1174             :     dbus_uint32_t err_min;
    1175             :     const char *err_msg;
    1176             : 
    1177           0 :     be_req = NULL;
    1178             : 
    1179           0 :     becli = talloc_get_type(user_data, struct be_client);
    1180           0 :     if (!becli) return EINVAL;
    1181             : 
    1182           0 :     if (!sbus_request_parse_or_finish(dbus_req,
    1183             :                                       DBUS_TYPE_UINT32, &type,
    1184             :                                       DBUS_TYPE_UINT32, &attr_type,
    1185             :                                       DBUS_TYPE_STRING, &filter,
    1186             :                                       DBUS_TYPE_STRING, &domain,
    1187             :                                       DBUS_TYPE_INVALID))
    1188           0 :         return EOK; /* handled */
    1189             : 
    1190           0 :     DEBUG(SSSDBG_FUNC_DATA,
    1191             :           "Got request for [%#x][%s][%d][%s]\n", type, be_req2str(type),
    1192             :           attr_type, filter);
    1193             : 
    1194             :     /* If we are offline and fast reply was requested
    1195             :      * return offline immediately
    1196             :      */
    1197           0 :     if ((type & BE_REQ_FAST) && becli->bectx->offstat.offline) {
    1198             :         /* Send back an immediate reply */
    1199           0 :         err_maj = DP_ERR_OFFLINE;
    1200           0 :         err_min = EAGAIN;
    1201           0 :         err_msg = "Fast reply - offline";
    1202             : 
    1203           0 :         ret = sbus_request_return_and_finish(dbus_req,
    1204             :                                              DBUS_TYPE_UINT16, &err_maj,
    1205             :                                              DBUS_TYPE_UINT32, &err_min,
    1206             :                                              DBUS_TYPE_STRING, &err_msg,
    1207             :                                              DBUS_TYPE_INVALID);
    1208           0 :         if (ret != EOK) {
    1209           0 :             return ret;
    1210             :         }
    1211             : 
    1212           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "Request processed. Returned %d,%d,%s\n",
    1213             :                   err_maj, err_min, err_msg);
    1214             : 
    1215           0 :         dbus_req = NULL;
    1216             :         /* This reply will be queued and sent
    1217             :          * when we reenter the mainloop.
    1218             :          *
    1219             :          * Continue processing in case we are
    1220             :          * going back online.
    1221             :          */
    1222             :     }
    1223             : 
    1224           0 :     be_req = be_req_create(becli, becli, becli->bectx,
    1225             :                            acctinfo_callback, dbus_req);
    1226           0 :     if (!be_req) {
    1227           0 :         err_maj = DP_ERR_FATAL;
    1228           0 :         err_min = ENOMEM;
    1229           0 :         err_msg = "Out of memory";
    1230           0 :         goto done;
    1231             :     }
    1232             : 
    1233           0 :     ret = be_req_set_domain(be_req, domain);
    1234           0 :     if (ret != EOK) {
    1235           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set request domain [%d]: %s\n",
    1236             :                                     ret, sss_strerror(ret));
    1237           0 :         err_maj = DP_ERR_FATAL;
    1238           0 :         err_min = ret;
    1239           0 :         err_msg = sss_strerror(ret);
    1240           0 :         goto done;
    1241             :     }
    1242             : 
    1243           0 :     req = talloc_zero(be_req, struct be_acct_req);
    1244           0 :     if (!req) {
    1245           0 :         err_maj = DP_ERR_FATAL;
    1246           0 :         err_min = ENOMEM;
    1247           0 :         err_msg = "Out of memory";
    1248           0 :         goto done;
    1249             :     }
    1250           0 :     req->entry_type = type;
    1251           0 :     req->attr_type = (int)attr_type;
    1252           0 :     req->domain = talloc_strdup(req, domain);
    1253           0 :     if (!req->domain) {
    1254           0 :         err_maj = DP_ERR_FATAL;
    1255           0 :         err_min = ENOMEM;
    1256           0 :         err_msg = "Out of memory";
    1257           0 :         goto done;
    1258             :     }
    1259             : 
    1260           0 :     if ((attr_type != BE_ATTR_CORE) &&
    1261           0 :         (attr_type != BE_ATTR_MEM) &&
    1262           0 :         (attr_type != BE_ATTR_ALL)) {
    1263             :         /* Unrecognized attr type */
    1264           0 :         err_maj = DP_ERR_FATAL;
    1265           0 :         err_min = EINVAL;
    1266           0 :         err_msg = "Invalid Attrs Parameter";
    1267           0 :         goto done;
    1268             :     }
    1269             : 
    1270           0 :     if (filter) {
    1271           0 :         ret = EOK;
    1272           0 :         if (strncmp(filter, "name=", 5) == 0) {
    1273           0 :             req->filter_type = BE_FILTER_NAME;
    1274           0 :             ret = split_name_extended(req, &filter[5],
    1275             :                                       &req->filter_value,
    1276             :                                       &req->extra_value);
    1277           0 :         } else if (strncmp(filter, "idnumber=", 9) == 0) {
    1278           0 :             req->filter_type = BE_FILTER_IDNUM;
    1279           0 :             ret = split_name_extended(req, &filter[9],
    1280             :                                       &req->filter_value,
    1281             :                                       &req->extra_value);
    1282           0 :         } else if (strncmp(filter, DP_SEC_ID"=", DP_SEC_ID_LEN + 1) == 0) {
    1283           0 :             req->filter_type = BE_FILTER_SECID;
    1284           0 :             ret = split_name_extended(req, &filter[DP_SEC_ID_LEN + 1],
    1285             :                                       &req->filter_value,
    1286             :                                       &req->extra_value);
    1287           0 :         } else if (strncmp(filter, DP_CERT"=", DP_CERT_LEN + 1) == 0) {
    1288           0 :             req->filter_type = BE_FILTER_CERT;
    1289           0 :             ret = split_name_extended(req, &filter[DP_CERT_LEN + 1],
    1290             :                                       &req->filter_value,
    1291             :                                       &req->extra_value);
    1292           0 :         } else if (strncmp(filter, DP_WILDCARD"=", DP_WILDCARD_LEN + 1) == 0) {
    1293           0 :             req->filter_type = BE_FILTER_WILDCARD;
    1294           0 :             ret = split_name_extended(req, &filter[DP_WILDCARD_LEN + 1],
    1295             :                                       &req->filter_value,
    1296             :                                       &req->extra_value);
    1297           0 :         } else if (strcmp(filter, ENUM_INDICATOR) == 0) {
    1298           0 :             req->filter_type = BE_FILTER_ENUM;
    1299           0 :             req->filter_value = NULL;
    1300           0 :             req->extra_value = NULL;
    1301             :         } else {
    1302           0 :             err_maj = DP_ERR_FATAL;
    1303           0 :             err_min = EINVAL;
    1304           0 :             err_msg = "Invalid Filter";
    1305           0 :             goto done;
    1306             :         }
    1307             : 
    1308           0 :         if (ret != EOK) {
    1309           0 :             err_maj = DP_ERR_FATAL;
    1310           0 :             err_min = EINVAL;
    1311           0 :             err_msg = "Invalid Filter";
    1312           0 :             goto done;
    1313             :         }
    1314             : 
    1315             :     } else {
    1316           0 :         err_maj = DP_ERR_FATAL;
    1317           0 :         err_min = EINVAL;
    1318           0 :         err_msg = "Missing Filter Parameter";
    1319           0 :         goto done;
    1320             :     }
    1321             : 
    1322           0 :     ret = be_file_account_request(be_req, req);
    1323           0 :     if (ret != EOK) {
    1324           0 :         err_maj = DP_ERR_FATAL;
    1325           0 :         err_min = ret;
    1326           0 :         err_msg = "Cannot file account request";
    1327           0 :         goto done;
    1328             :     }
    1329             : 
    1330           0 :     return EOK;
    1331             : 
    1332             : done:
    1333           0 :     if (be_req) {
    1334           0 :         talloc_free(be_req);
    1335             :     }
    1336             : 
    1337           0 :     if (dbus_req) {
    1338           0 :         ret = sbus_request_return_and_finish(dbus_req,
    1339             :                                              DBUS_TYPE_UINT16, &err_maj,
    1340             :                                              DBUS_TYPE_UINT32, &err_min,
    1341             :                                              DBUS_TYPE_STRING, &err_msg,
    1342             :                                              DBUS_TYPE_INVALID);
    1343           0 :         if (ret != EOK) {
    1344           0 :             return ret;
    1345             :         }
    1346             : 
    1347           0 :         DEBUG(SSSDBG_CONF_SETTINGS, "Request processed. Returned %d,%d,%s\n",
    1348             :                   err_maj, err_min, err_msg);
    1349             :     }
    1350             : 
    1351           0 :     return EOK;
    1352             : }
    1353             : 
    1354           0 : static void be_pam_handler_callback(struct be_req *req,
    1355             :                                     int dp_err_type,
    1356             :                                     int errnum,
    1357             :                                     const char *errstr)
    1358             : {
    1359           0 :     struct be_client *becli = req->becli;
    1360             :     struct sbus_request *dbus_req;
    1361             :     struct pam_data *pd;
    1362             :     DBusMessage *reply;
    1363             :     dbus_bool_t dbret;
    1364             :     errno_t ret;
    1365             : 
    1366           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Backend returned: (%d, %d, %s) [%s]\n",
    1367             :               dp_err_type, errnum, errstr?errstr:"<NULL>",
    1368             :               dp_pam_err_to_string(req, dp_err_type, errnum));
    1369             : 
    1370           0 :     pd = talloc_get_type(be_req_get_data(req), struct pam_data);
    1371             : 
    1372           0 :     if (pd->cmd == SSS_PAM_ACCT_MGMT &&
    1373           0 :         pd->pam_status == PAM_SUCCESS &&
    1374           0 :         req->phase == REQ_PHASE_ACCESS &&
    1375             :         dp_err_type == DP_ERR_OK) {
    1376           0 :         if (!becli->bectx->bet_info[BET_SELINUX].bet_ops) {
    1377           0 :             DEBUG(SSSDBG_TRACE_FUNC,
    1378             :                   "SELinux provider doesn't exist, "
    1379             :                    "not sending the request to it.\n");
    1380             :         } else {
    1381           0 :             req->phase = REQ_PHASE_SELINUX;
    1382             : 
    1383             :             /* Now is the time to call SELinux provider */
    1384           0 :             ret = be_file_request(becli->bectx->bet_info[BET_SELINUX].pvt_bet_data,
    1385             :                                   req,
    1386           0 :                                   becli->bectx->bet_info[BET_SELINUX].bet_ops->handler);
    1387           0 :             if (ret != EOK) {
    1388           0 :                 DEBUG(SSSDBG_OP_FAILURE, "be_file_request failed.\n");
    1389           0 :                 goto done;
    1390             :             }
    1391           0 :             return;
    1392             :         }
    1393             :     }
    1394             : 
    1395           0 :     DEBUG(SSSDBG_CONF_SETTINGS,
    1396             :           "Sending result [%d][%s]\n", pd->pam_status, pd->domain);
    1397           0 :     dbus_req = (struct sbus_request *)req->pvt;
    1398           0 :     reply = dbus_message_new_method_return(dbus_req->message);
    1399           0 :     if (reply == NULL) {
    1400           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1401             :               "dbus_message_new_method_return failed, cannot send reply.\n");
    1402           0 :         goto done;
    1403             :     }
    1404             : 
    1405           0 :     dbret = dp_pack_pam_response(reply, pd);
    1406           0 :     if (!dbret) {
    1407           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
    1408           0 :         dbus_message_unref(reply);
    1409           0 :         goto done;
    1410             :     }
    1411             : 
    1412           0 :     sbus_request_finish(dbus_req, reply);
    1413           0 :     dbus_message_unref(reply);
    1414             : 
    1415           0 :     DEBUG(SSSDBG_CONF_SETTINGS,
    1416             :           "Sent result [%d][%s]\n", pd->pam_status, pd->domain);
    1417             : 
    1418             : done:
    1419           0 :     talloc_free(req);
    1420             : }
    1421             : 
    1422           0 : static int be_pam_handler(struct sbus_request *dbus_req, void *user_data)
    1423             : {
    1424             :     DBusError dbus_error;
    1425             :     DBusMessage *reply;
    1426             :     struct be_client *becli;
    1427             :     dbus_bool_t ret;
    1428           0 :     struct pam_data *pd = NULL;
    1429           0 :     struct be_req *be_req = NULL;
    1430           0 :     enum bet_type target = BET_NULL;
    1431             : 
    1432           0 :     becli = talloc_get_type(user_data, struct be_client);
    1433           0 :     if (!becli) return EINVAL;
    1434             : 
    1435           0 :     be_req = be_req_create(becli, becli, becli->bectx,
    1436             :                            be_pam_handler_callback, dbus_req);
    1437           0 :     if (!be_req) {
    1438           0 :         DEBUG(SSSDBG_TRACE_LIBS, "talloc_zero failed.\n");
    1439           0 :         return ENOMEM;
    1440             :     }
    1441             : 
    1442           0 :     dbus_error_init(&dbus_error);
    1443             : 
    1444           0 :     ret = dp_unpack_pam_request(dbus_req->message, be_req, &pd, &dbus_error);
    1445           0 :     if (!ret) {
    1446           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse message!\n");
    1447           0 :         talloc_free(be_req);
    1448           0 :         return EIO;
    1449             :     }
    1450             : 
    1451           0 :     pd->pam_status = PAM_SYSTEM_ERR;
    1452           0 :     if (pd->domain == NULL) {
    1453           0 :         pd->domain = talloc_strdup(pd, becli->bectx->domain->name);
    1454           0 :         if (pd->domain == NULL) {
    1455           0 :             talloc_free(be_req);
    1456           0 :             return ENOMEM;
    1457             :         }
    1458             :     }
    1459             : 
    1460           0 :     ret = be_req_set_domain(be_req, pd->domain);
    1461           0 :     if (ret != EOK) {
    1462           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set request domain [%d]: %s\n",
    1463             :                                     ret, sss_strerror(ret));
    1464           0 :         pd->pam_status = PAM_SYSTEM_ERR;
    1465           0 :         goto done;
    1466             :     }
    1467             : 
    1468           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Got request with the following data\n");
    1469           0 :     DEBUG_PAM_DATA(SSSDBG_CONF_SETTINGS, pd);
    1470             : 
    1471           0 :     switch (pd->cmd) {
    1472             :         case SSS_PAM_AUTHENTICATE:
    1473             :         case SSS_PAM_PREAUTH:
    1474           0 :             target = BET_AUTH;
    1475           0 :             break;
    1476             :         case SSS_PAM_ACCT_MGMT:
    1477           0 :             target = BET_ACCESS;
    1478           0 :             be_req->phase = REQ_PHASE_ACCESS;
    1479           0 :             break;
    1480             :         case SSS_PAM_CHAUTHTOK:
    1481             :         case SSS_PAM_CHAUTHTOK_PRELIM:
    1482           0 :             target = BET_CHPASS;
    1483           0 :             break;
    1484             :         case SSS_PAM_OPEN_SESSION:
    1485             :         case SSS_PAM_SETCRED:
    1486             :         case SSS_PAM_CLOSE_SESSION:
    1487           0 :             pd->pam_status = PAM_SUCCESS;
    1488           0 :             goto done;
    1489             :             break;
    1490             :         default:
    1491           0 :             DEBUG(SSSDBG_TRACE_LIBS,
    1492             :                   "Unsupported PAM command [%d].\n", pd->cmd);
    1493           0 :             pd->pam_status = PAM_MODULE_UNKNOWN;
    1494           0 :             goto done;
    1495             :     }
    1496             : 
    1497             :     /* return PAM_MODULE_UNKNOWN if corresponding backend target is not
    1498             :      * configured
    1499             :      */
    1500           0 :     if (!becli->bectx->bet_info[target].bet_ops) {
    1501           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Undefined backend target.\n");
    1502           0 :         pd->pam_status = PAM_MODULE_UNKNOWN;
    1503           0 :         goto done;
    1504             :     }
    1505             : 
    1506           0 :     be_req->req_data = pd;
    1507             : 
    1508           0 :     ret = be_file_request(becli->bectx->bet_info[target].pvt_bet_data,
    1509             :                           be_req,
    1510           0 :                           becli->bectx->bet_info[target].bet_ops->handler);
    1511           0 :     if (ret != EOK) {
    1512           0 :         DEBUG(SSSDBG_TRACE_LIBS, "be_file_request failed.\n");
    1513           0 :         goto done;
    1514             :     }
    1515             : 
    1516           0 :     return EOK;
    1517             : 
    1518             : done:
    1519             : 
    1520           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Sending result [%d][%s]\n",
    1521             :               pd->pam_status, pd->domain);
    1522             : 
    1523           0 :     reply = dbus_message_new_method_return(dbus_req->message);
    1524           0 :     if (reply == NULL) {
    1525           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    1526             :               "dbus_message_new_method_return failed, cannot send reply.\n");
    1527           0 :         return ENOMEM;
    1528             :     }
    1529             : 
    1530           0 :     ret = dp_pack_pam_response(reply, pd);
    1531           0 :     if (!ret) {
    1532           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate dbus reply\n");
    1533           0 :         talloc_free(be_req);
    1534           0 :         dbus_message_unref(reply);
    1535           0 :         return EIO;
    1536             :     }
    1537             : 
    1538             :     /* send reply back immediately */
    1539           0 :     sbus_request_finish(dbus_req, reply);
    1540           0 :     dbus_message_unref(reply);
    1541             : 
    1542           0 :     talloc_free(be_req);
    1543             : 
    1544           0 :     return EOK;
    1545             : }
    1546             : 
    1547           0 : static void be_sudo_handler_reply(struct sbus_request *dbus_req,
    1548             :                                   dbus_uint16_t dp_err,
    1549             :                                   dbus_uint32_t dp_ret,
    1550             :                                   const char *errstr)
    1551             : {
    1552           0 :     const char *err_msg = NULL;
    1553             : 
    1554           0 :     if (dbus_req == NULL) {
    1555           0 :         return;
    1556             :     }
    1557             : 
    1558           0 :     err_msg = errstr ? errstr : "No errmsg set\n";
    1559           0 :     sbus_request_return_and_finish(dbus_req,
    1560             :                                    DBUS_TYPE_UINT16, &dp_err,
    1561             :                                    DBUS_TYPE_UINT32, &dp_ret,
    1562             :                                    DBUS_TYPE_STRING, &err_msg,
    1563             :                                    DBUS_TYPE_INVALID);
    1564             : 
    1565           0 :     DEBUG(SSSDBG_FUNC_DATA, "SUDO Backend returned: (%d, %d, %s)\n",
    1566             :                              dp_err, dp_ret, errstr ? errstr : "<NULL>");
    1567             : }
    1568             : 
    1569           0 : static void be_sudo_handler_callback(struct be_req *req,
    1570             :                                      int dp_err,
    1571             :                                      int dp_ret,
    1572             :                                      const char *errstr)
    1573             : {
    1574             :     struct sbus_request *dbus_req;
    1575           0 :     dbus_req = (struct sbus_request *)(req->pvt);
    1576             : 
    1577           0 :     be_sudo_handler_reply(dbus_req, dp_err, dp_ret, errstr);
    1578             : 
    1579           0 :     talloc_free(req);
    1580           0 : }
    1581             : 
    1582           0 : static int be_sudo_handler(struct sbus_request *dbus_req, void *user_data)
    1583             : {
    1584             :     DBusError dbus_error;
    1585             :     DBusMessageIter iter;
    1586             :     DBusMessageIter array_iter;
    1587           0 :     struct be_client *be_cli = NULL;
    1588           0 :     struct be_req *be_req = NULL;
    1589           0 :     struct be_sudo_req *sudo_req = NULL;
    1590           0 :     int ret = 0;
    1591             :     uint32_t type;
    1592           0 :     uint32_t rules_num = 0;
    1593           0 :     const char *rule = NULL;
    1594           0 :     const char *err_msg = NULL;
    1595             :     int i;
    1596             : 
    1597           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Entering be_sudo_handler()\n");
    1598             : 
    1599           0 :     be_cli = talloc_get_type(user_data, struct be_client);
    1600           0 :     if (be_cli == NULL) {
    1601           0 :         return EINVAL;
    1602             :     }
    1603             : 
    1604             :     /* create be request */
    1605           0 :     be_req = be_req_create(be_cli, be_cli, be_cli->bectx,
    1606             :                            be_sudo_handler_callback, dbus_req);
    1607           0 :     if (be_req == NULL) {
    1608           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
    1609           0 :         return ENOMEM;
    1610             :     }
    1611             : 
    1612           0 :     dbus_error_init(&dbus_error);
    1613           0 :     dbus_message_iter_init(dbus_req->message, &iter);
    1614             : 
    1615             :     /* get type of the request */
    1616           0 :     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
    1617           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n");
    1618           0 :         ret = EIO;
    1619           0 :         err_msg = "Invalid D-Bus message format";
    1620           0 :         goto fail;
    1621             :     }
    1622           0 :     dbus_message_iter_get_basic(&iter, &type);
    1623           0 :     dbus_message_iter_next(&iter); /* step behind the request type */
    1624             : 
    1625             :     /* If we are offline and fast reply was requested
    1626             :      * return offline immediately
    1627             :      */
    1628           0 :     if ((type & BE_REQ_FAST) && be_cli->bectx->offstat.offline) {
    1629           0 :         be_sudo_handler_reply(dbus_req, DP_ERR_OFFLINE, EAGAIN,
    1630             :                               "Fast reply - offline");
    1631           0 :         be_req->pvt = dbus_req = NULL;
    1632             :         /* This reply will be queued and sent
    1633             :          * when we reenter the mainloop.
    1634             :          *
    1635             :          * Continue processing in case we are
    1636             :          * going back online.
    1637             :          */
    1638             :     }
    1639             : 
    1640             :     /* get and set sudo request data */
    1641           0 :     sudo_req = talloc_zero(be_req, struct be_sudo_req);
    1642           0 :     if (sudo_req == NULL) {
    1643           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
    1644           0 :         goto fail;
    1645             :     }
    1646             : 
    1647           0 :     sudo_req->type = (~BE_REQ_FAST) & type;
    1648             : 
    1649             :     /* get additional arguments according to the request type */
    1650           0 :     switch (sudo_req->type) {
    1651             :     case BE_REQ_SUDO_FULL:
    1652             :         /* no arguments required */
    1653           0 :         break;
    1654             :     case BE_REQ_SUDO_RULES:
    1655             :         /* additional arguments:
    1656             :          * rules_num
    1657             :          * rules[rules_num]
    1658             :          */
    1659             :         /* read rules_num */
    1660           0 :         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) {
    1661           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n");
    1662           0 :             ret = EIO;
    1663           0 :             err_msg = "Invalid D-Bus message format";
    1664           0 :             goto fail;
    1665             :         }
    1666             : 
    1667           0 :         dbus_message_iter_get_basic(&iter, &rules_num);
    1668             : 
    1669           0 :         sudo_req->rules = talloc_array(sudo_req, char*, rules_num + 1);
    1670           0 :         if (sudo_req->rules == NULL) {
    1671           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n");
    1672           0 :             ret = ENOMEM;
    1673           0 :             goto fail;
    1674             :         }
    1675             : 
    1676           0 :         dbus_message_iter_next(&iter);
    1677             : 
    1678           0 :         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
    1679           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n");
    1680           0 :             ret = EIO;
    1681           0 :             err_msg = "Invalid D-Bus message format";
    1682           0 :             goto fail;
    1683             :         }
    1684             : 
    1685           0 :         dbus_message_iter_recurse(&iter, &array_iter);
    1686             : 
    1687             :         /* read the rules */
    1688           0 :         for (i = 0; i < rules_num; i++) {
    1689           0 :             if (dbus_message_iter_get_arg_type(&array_iter)
    1690             :                     != DBUS_TYPE_STRING) {
    1691           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n");
    1692           0 :                 ret = EIO;
    1693           0 :                 err_msg = "Invalid D-Bus message format";
    1694           0 :                 goto fail;
    1695             :             }
    1696             : 
    1697           0 :             dbus_message_iter_get_basic(&array_iter, &rule);
    1698           0 :             sudo_req->rules[i] = talloc_strdup(sudo_req->rules, rule);
    1699           0 :             if (sudo_req->rules[i] == NULL) {
    1700           0 :                 DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
    1701           0 :                 ret = ENOMEM;
    1702           0 :                 goto fail;
    1703             :             }
    1704             : 
    1705           0 :             dbus_message_iter_next(&array_iter);
    1706             :         }
    1707             : 
    1708           0 :         sudo_req->rules[rules_num] = NULL;
    1709             : 
    1710           0 :         break;
    1711             :     default:
    1712           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type %d\n", sudo_req->type);
    1713           0 :         ret = EINVAL;
    1714           0 :         err_msg = "Invalid DP request type";
    1715           0 :         goto fail;
    1716             :     }
    1717             : 
    1718           0 :     be_req->req_data = sudo_req;
    1719             : 
    1720             :     /* return an error if corresponding backend target is not configured */
    1721           0 :     if (!be_cli->bectx->bet_info[BET_SUDO].bet_ops) {
    1722           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Undefined backend target.\n");
    1723           0 :         ret = ENODEV;
    1724           0 :         goto fail;
    1725             :     }
    1726             : 
    1727           0 :     ret = be_file_request(be_cli->bectx->bet_info[BET_SUDO].pvt_bet_data,
    1728             :                           be_req,
    1729           0 :                           be_cli->bectx->bet_info[BET_SUDO].bet_ops->handler);
    1730           0 :     if (ret != EOK) {
    1731           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "be_file_request failed.\n");
    1732           0 :         err_msg = "Cannot file back end request";
    1733           0 :         goto fail;
    1734             :     }
    1735             : 
    1736           0 :     return EOK;
    1737             : 
    1738             : fail:
    1739             :     /* send reply back immediately */
    1740           0 :     be_sudo_handler_callback(be_req, DP_ERR_FATAL, ret,
    1741             :                              err_msg ? err_msg : strerror(ret));
    1742           0 :     return EOK;
    1743             : }
    1744             : 
    1745             : static void be_autofs_handler_callback(struct be_req *req,
    1746             :                                        int dp_err_type,
    1747             :                                        int errnum,
    1748             :                                        const char *errstr);
    1749             : 
    1750           0 : static int be_autofs_handler(struct sbus_request *dbus_req, void *user_data)
    1751             : {
    1752           0 :     struct be_client *be_cli = NULL;
    1753           0 :     struct be_req *be_req = NULL;
    1754           0 :     struct be_autofs_req *be_autofs_req = NULL;
    1755           0 :     int ret = 0;
    1756             :     uint32_t type;
    1757             :     char *filter;
    1758             :     char *filter_val;
    1759             :     dbus_uint16_t err_maj;
    1760             :     dbus_uint32_t err_min;
    1761             :     const char *err_msg;
    1762             : 
    1763           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Entering be_autofs_handler()\n");
    1764             : 
    1765           0 :     be_cli = talloc_get_type(user_data, struct be_client);
    1766           0 :     if (be_cli == NULL) {
    1767           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Cannot get back end client context\n");
    1768           0 :         return EINVAL;
    1769             :     }
    1770             : 
    1771           0 :     if (!sbus_request_parse_or_finish(dbus_req,
    1772             :                                       DBUS_TYPE_UINT32, &type,
    1773             :                                       DBUS_TYPE_STRING, &filter,
    1774             :                                       DBUS_TYPE_INVALID))
    1775           0 :         return EOK; /* handled */
    1776             : 
    1777             :     /* If we are offline and fast reply was requested
    1778             :      * return offline immediately
    1779             :      */
    1780           0 :     if ((type & BE_REQ_FAST) && be_cli->bectx->offstat.offline) {
    1781             :         /* Send back an immediate reply */
    1782           0 :         err_maj = DP_ERR_OFFLINE;
    1783           0 :         err_min = EAGAIN;
    1784           0 :         err_msg = "Fast reply - offline";
    1785             : 
    1786           0 :         ret = sbus_request_return_and_finish(dbus_req,
    1787             :                                              DBUS_TYPE_UINT16, &err_maj,
    1788             :                                              DBUS_TYPE_UINT32, &err_min,
    1789             :                                              DBUS_TYPE_STRING, &err_msg,
    1790             :                                              DBUS_TYPE_INVALID);
    1791           0 :         if (ret != EOK) {
    1792           0 :             return ret;
    1793             :         }
    1794             : 
    1795           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Request processed. Returned %d,%d,%s\n",
    1796             :               err_maj, err_min, err_msg);
    1797             : 
    1798           0 :         dbus_req = NULL;
    1799             :         /* This reply will be queued and sent
    1800             :          * when we reenter the mainloop.
    1801             :          *
    1802             :          * Continue processing in case we are
    1803             :          * going back online.
    1804             :          */
    1805             :     }
    1806             : 
    1807           0 :     if (filter) {
    1808           0 :         if (strncmp(filter, "mapname=", 8) == 0) {
    1809           0 :             filter_val = &filter[8];
    1810             :         } else {
    1811           0 :             err_maj = DP_ERR_FATAL;
    1812           0 :             err_min = EINVAL;
    1813           0 :             err_msg = "Invalid Filter";
    1814           0 :             goto done;
    1815             :         }
    1816             :     } else {
    1817           0 :         err_maj = DP_ERR_FATAL;
    1818           0 :         err_min = EINVAL;
    1819           0 :         err_msg = "Missing Filter Parameter";
    1820           0 :         goto done;
    1821             :     }
    1822             : 
    1823             :     /* create be request */
    1824           0 :     be_req = be_req_create(be_cli, be_cli, be_cli->bectx,
    1825             :                            be_autofs_handler_callback, dbus_req);
    1826           0 :     if (be_req == NULL) {
    1827           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
    1828           0 :         err_maj = DP_ERR_FATAL;
    1829           0 :         err_min = ENOMEM;
    1830           0 :         err_msg = "Out of memory";
    1831           0 :         goto done;
    1832             :     }
    1833             : 
    1834             :     /* set autofs request data */
    1835           0 :     be_autofs_req = talloc_zero(be_req, struct be_autofs_req);
    1836           0 :     if (be_autofs_req == NULL) {
    1837           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
    1838           0 :         err_maj = DP_ERR_FATAL;
    1839           0 :         err_min = ENOMEM;
    1840           0 :         err_msg = "Out of memory";
    1841           0 :         goto done;
    1842             :     }
    1843             : 
    1844           0 :     be_autofs_req->mapname = talloc_strdup(be_autofs_req, filter_val);
    1845           0 :     if (be_autofs_req->mapname == NULL) {
    1846           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
    1847           0 :         err_maj = DP_ERR_FATAL;
    1848           0 :         err_min = ENOMEM;
    1849           0 :         err_msg = "Out of memory";
    1850           0 :         goto done;
    1851             :     }
    1852             : 
    1853           0 :     be_req->req_data = be_autofs_req;
    1854             : 
    1855           0 :     if (!be_cli->bectx->bet_info[BET_AUTOFS].bet_ops) {
    1856           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Undefined backend target.\n");
    1857           0 :         err_maj = DP_ERR_FATAL;
    1858           0 :         err_min = ENODEV;
    1859           0 :         err_msg = "Autofs back end target is not configured";
    1860           0 :         goto done;
    1861             :     }
    1862             : 
    1863           0 :     ret = be_file_request(be_cli->bectx->bet_info[BET_AUTOFS].pvt_bet_data,
    1864             :                           be_req,
    1865           0 :                           be_cli->bectx->bet_info[BET_AUTOFS].bet_ops->handler);
    1866           0 :     if (ret != EOK) {
    1867           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "be_file_request failed.\n");
    1868           0 :         err_maj = DP_ERR_FATAL;
    1869           0 :         err_min = ENODEV;
    1870           0 :         err_msg = "Cannot file back end request";
    1871           0 :         goto done;
    1872             :     }
    1873             : 
    1874           0 :     return EOK;
    1875             : 
    1876             : done:
    1877           0 :     if (be_req) {
    1878           0 :         talloc_free(be_req);
    1879             :     }
    1880             : 
    1881           0 :     if (dbus_req) {
    1882           0 :         ret = sbus_request_return_and_finish(dbus_req,
    1883             :                                              DBUS_TYPE_UINT16, &err_maj,
    1884             :                                              DBUS_TYPE_UINT32, &err_min,
    1885             :                                              DBUS_TYPE_STRING, &err_msg,
    1886             :                                              DBUS_TYPE_INVALID);
    1887           0 :         if (ret != EOK) {
    1888           0 :             return ret;
    1889             :         }
    1890             : 
    1891           0 :         DEBUG(SSSDBG_TRACE_LIBS, "Request processed. Returned %d,%d,%s\n",
    1892             :               err_maj, err_min, err_msg);
    1893             :     }
    1894             : 
    1895           0 :     return EOK;
    1896             : }
    1897             : 
    1898           0 : static void be_autofs_handler_callback(struct be_req *req,
    1899             :                                        int dp_err_type,
    1900             :                                        int errnum,
    1901             :                                        const char *errstr)
    1902             : {
    1903             :     struct sbus_request *dbus_req;
    1904           0 :     dbus_uint16_t err_maj = 0;
    1905           0 :     dbus_uint32_t err_min = 0;
    1906           0 :     const char *err_msg = NULL;
    1907             : 
    1908           0 :     dbus_req = (struct sbus_request *)req->pvt;
    1909             : 
    1910           0 :     if (dbus_req) {
    1911             :         /* Return a reply if one was requested
    1912             :          * There may not be one if this request began
    1913             :          * while we were offline
    1914             :          */
    1915             : 
    1916           0 :         err_maj = dp_err_type;
    1917           0 :         err_min = errnum;
    1918           0 :         if (errstr) {
    1919           0 :             err_msg = errstr;
    1920             :         } else {
    1921           0 :             err_msg = dp_pam_err_to_string(req, dp_err_type, errnum);
    1922             :         }
    1923           0 :         if (!err_msg) {
    1924           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
    1925             :                   "Failed to set err_msg, Out of memory?\n");
    1926           0 :             err_msg = "OOM";
    1927             :         }
    1928             : 
    1929           0 :         sbus_request_return_and_finish(dbus_req,
    1930             :                                        DBUS_TYPE_UINT16, &err_maj,
    1931             :                                        DBUS_TYPE_UINT32, &err_min,
    1932             :                                        DBUS_TYPE_STRING, &err_msg,
    1933             :                                        DBUS_TYPE_INVALID);
    1934             : 
    1935           0 :         DEBUG(SSSDBG_TRACE_LIBS,
    1936             :               "Request processed. Returned %d,%d,%s\n",
    1937             :                err_maj, err_min, err_msg);
    1938             :     }
    1939             : 
    1940             :     /* finally free the request */
    1941           0 :     talloc_free(req);
    1942           0 : }
    1943             : 
    1944           0 : static int be_host_handler(struct sbus_request *dbus_req, void *user_data)
    1945             : {
    1946             :     struct be_host_req *req;
    1947             :     struct be_req *be_req;
    1948             :     struct be_client *becli;
    1949             :     uint32_t flags;
    1950             :     char *filter;
    1951             :     int ret;
    1952             :     dbus_uint16_t err_maj;
    1953             :     dbus_uint32_t err_min;
    1954             :     const char *err_msg;
    1955             : 
    1956           0 :     be_req = NULL;
    1957             : 
    1958           0 :     becli = talloc_get_type(user_data, struct be_client);
    1959           0 :     if (!becli) return EINVAL;
    1960             : 
    1961           0 :     if (!sbus_request_parse_or_finish(dbus_req,
    1962             :                                       DBUS_TYPE_UINT32, &flags,
    1963             :                                       DBUS_TYPE_STRING, &filter,
    1964             :                                       DBUS_TYPE_INVALID))
    1965           0 :         return EOK; /* request finished */
    1966             : 
    1967           0 :     DEBUG(SSSDBG_TRACE_LIBS,
    1968             :           "Got request for [%u][%s]\n", flags, filter);
    1969             : 
    1970             :     /* If we are offline and fast reply was requested
    1971             :      * return offline immediately
    1972             :      */
    1973           0 :     if ((flags & BE_REQ_FAST) && becli->bectx->offstat.offline) {
    1974             :         /* Send back an immediate reply */
    1975           0 :         err_maj = DP_ERR_OFFLINE;
    1976           0 :         err_min = EAGAIN;
    1977           0 :         err_msg = "Fast reply - offline";
    1978             : 
    1979           0 :         ret = sbus_request_return_and_finish(dbus_req,
    1980             :                                              DBUS_TYPE_UINT16, &err_maj,
    1981             :                                              DBUS_TYPE_UINT32, &err_min,
    1982             :                                              DBUS_TYPE_STRING, &err_msg,
    1983             :                                              DBUS_TYPE_INVALID);
    1984           0 :         if (ret != EOK) {
    1985           0 :             return ret;
    1986             :         }
    1987             : 
    1988           0 :         DEBUG(SSSDBG_TRACE_LIBS,
    1989             :               "Request processed. Returned %d,%d,%s\n",
    1990             :                err_maj, err_min, err_msg);
    1991             : 
    1992           0 :         dbus_req = NULL;
    1993             :         /* This reply will be queued and sent
    1994             :          * when we reenter the mainloop.
    1995             :          *
    1996             :          * Continue processing in case we are
    1997             :          * going back online.
    1998             :          */
    1999             :     }
    2000             : 
    2001           0 :     be_req = be_req_create(becli, becli, becli->bectx,
    2002             :                            acctinfo_callback, dbus_req);
    2003           0 :     if (!be_req) {
    2004           0 :         err_maj = DP_ERR_FATAL;
    2005           0 :         err_min = ENOMEM;
    2006           0 :         err_msg = "Out of memory";
    2007           0 :         goto done;
    2008             :     }
    2009             : 
    2010           0 :     req = talloc(be_req, struct be_host_req);
    2011           0 :     if (!req) {
    2012           0 :         err_maj = DP_ERR_FATAL;
    2013           0 :         err_min = ENOMEM;
    2014           0 :         err_msg = "Out of memory";
    2015           0 :         goto done;
    2016             :     }
    2017           0 :     req->type = BE_REQ_HOST | (flags & BE_REQ_FAST);
    2018             : 
    2019           0 :     be_req->req_data = req;
    2020             : 
    2021           0 :     if (filter) {
    2022           0 :         ret = strncmp(filter, "name=", 5);
    2023           0 :         if (ret == 0) {
    2024           0 :             req->filter_type = BE_FILTER_NAME;
    2025           0 :             ret = split_name_extended(req, &filter[5],
    2026             :                                       &req->name,
    2027             :                                       &req->alias);
    2028             :         }
    2029             : 
    2030           0 :         if (ret) {
    2031           0 :             err_maj = DP_ERR_FATAL;
    2032           0 :             err_min = EINVAL;
    2033           0 :             err_msg = "Invalid Filter";
    2034           0 :             goto done;
    2035             :         }
    2036             :     } else {
    2037           0 :         err_maj = DP_ERR_FATAL;
    2038           0 :         err_min = EINVAL;
    2039           0 :         err_msg = "Missing Filter Parameter";
    2040           0 :         goto done;
    2041             :     }
    2042             : 
    2043             :     /* process request */
    2044             : 
    2045           0 :     if (!becli->bectx->bet_info[BET_HOSTID].bet_ops) {
    2046           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Undefined backend target.\n");
    2047           0 :         err_maj = DP_ERR_FATAL;
    2048           0 :         err_min = ENODEV;
    2049           0 :         err_msg = "HostID back end target is not configured";
    2050           0 :         goto done;
    2051             :     }
    2052             : 
    2053           0 :     ret = be_file_request(becli->bectx->bet_info[BET_HOSTID].pvt_bet_data,
    2054             :                           be_req,
    2055           0 :                           becli->bectx->bet_info[BET_HOSTID].bet_ops->handler);
    2056           0 :     if (ret != EOK) {
    2057           0 :         err_maj = DP_ERR_FATAL;
    2058           0 :         err_min = ret;
    2059           0 :         err_msg = "Failed to file request";
    2060           0 :         goto done;
    2061             :     }
    2062             : 
    2063           0 :     return EOK;
    2064             : 
    2065             : done:
    2066           0 :     if (be_req) {
    2067           0 :         talloc_free(be_req);
    2068             :     }
    2069             : 
    2070           0 :     if (dbus_req) {
    2071           0 :         ret = sbus_request_return_and_finish(dbus_req,
    2072             :                                              DBUS_TYPE_UINT16, &err_maj,
    2073             :                                              DBUS_TYPE_UINT32, &err_min,
    2074             :                                              DBUS_TYPE_STRING, &err_msg,
    2075             :                                              DBUS_TYPE_INVALID);
    2076           0 :         if (ret != EOK) {
    2077           0 :             return ret;
    2078             :         }
    2079             : 
    2080           0 :         DEBUG(SSSDBG_TRACE_LIBS,
    2081             :               "Request processed. Returned %d,%d,%s\n",
    2082             :                err_maj, err_min, err_msg);
    2083             :     }
    2084             : 
    2085           0 :     return EOK;
    2086             : }
    2087             : 
    2088           0 : static int be_client_destructor(void *ctx)
    2089             : {
    2090           0 :     struct be_client *becli = talloc_get_type(ctx, struct be_client);
    2091           0 :     if (becli->bectx) {
    2092           0 :         if (becli->bectx->nss_cli == becli) {
    2093           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Removed NSS client\n");
    2094           0 :             becli->bectx->nss_cli = NULL;
    2095           0 :         } else if (becli->bectx->pam_cli == becli) {
    2096           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Removed PAM client\n");
    2097           0 :             becli->bectx->pam_cli = NULL;
    2098           0 :         } else if (becli->bectx->sudo_cli == becli) {
    2099           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Removed SUDO client\n");
    2100           0 :             becli->bectx->sudo_cli = NULL;
    2101           0 :         } else if (becli->bectx->autofs_cli == becli) {
    2102           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Removed autofs client\n");
    2103           0 :             becli->bectx->autofs_cli = NULL;
    2104           0 :         } else if (becli->bectx->ssh_cli == becli) {
    2105           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Removed SSH client\n");
    2106           0 :             becli->bectx->ssh_cli = NULL;
    2107           0 :         } else if (becli->bectx->pac_cli == becli) {
    2108           0 :             DEBUG(SSSDBG_TRACE_FUNC, "Removed PAC client\n");
    2109           0 :             becli->bectx->pac_cli = NULL;
    2110             :         } else {
    2111           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "Unknown client removed ...\n");
    2112             :         }
    2113             :     }
    2114           0 :     return 0;
    2115             : }
    2116             : 
    2117           0 : static int client_registration(struct sbus_request *dbus_req, void *data)
    2118             : {
    2119           0 :     dbus_uint16_t version = DATA_PROVIDER_VERSION;
    2120             :     struct sbus_connection *conn;
    2121             :     struct be_client *becli;
    2122             :     DBusError dbus_error;
    2123             :     dbus_uint16_t cli_ver;
    2124             :     char *cli_name;
    2125             :     dbus_bool_t dbret;
    2126             :     int ret;
    2127             : 
    2128           0 :     conn = dbus_req->conn;
    2129           0 :     becli = talloc_get_type(data, struct be_client);
    2130           0 :     if (!becli) {
    2131           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Connection holds no valid init data\n");
    2132           0 :         return EINVAL;
    2133             :     }
    2134             : 
    2135             :     /* First thing, cancel the timeout */
    2136           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Cancel DP ID timeout [%p]\n", becli->timeout);
    2137           0 :     talloc_zfree(becli->timeout);
    2138             : 
    2139           0 :     dbus_error_init(&dbus_error);
    2140             : 
    2141           0 :     dbret = dbus_message_get_args(dbus_req->message, &dbus_error,
    2142             :                                   DBUS_TYPE_UINT16, &cli_ver,
    2143             :                                   DBUS_TYPE_STRING, &cli_name,
    2144             :                                   DBUS_TYPE_INVALID);
    2145           0 :     if (!dbret) {
    2146           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    2147             :               "Failed to parse message, killing connection\n");
    2148           0 :         if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
    2149           0 :         sbus_disconnect(conn);
    2150             :         /* FIXME: should we just talloc_zfree(conn) ? */
    2151           0 :         return EIO;
    2152             :     }
    2153             : 
    2154           0 :     if (strcasecmp(cli_name, "NSS") == 0) {
    2155           0 :         becli->bectx->nss_cli = becli;
    2156           0 :     } else if (strcasecmp(cli_name, "PAM") == 0) {
    2157           0 :         becli->bectx->pam_cli = becli;
    2158           0 :     } else if (strcasecmp(cli_name, "SUDO") == 0) {
    2159           0 :         becli->bectx->sudo_cli = becli;
    2160           0 :     } else if (strcasecmp(cli_name, "autofs") == 0) {
    2161           0 :         becli->bectx->autofs_cli = becli;
    2162           0 :     } else if (strcasecmp(cli_name, "SSH") == 0) {
    2163           0 :         becli->bectx->ssh_cli = becli;
    2164           0 :     } else if (strcasecmp(cli_name, "PAC") == 0) {
    2165           0 :         becli->bectx->pac_cli = becli;
    2166           0 :     } else if (strcasecmp(cli_name, "InfoPipe") == 0) {
    2167           0 :         becli->bectx->ifp_cli = becli;
    2168             :     } else {
    2169           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unknown client! [%s]\n", cli_name);
    2170             :     }
    2171           0 :     talloc_set_destructor((TALLOC_CTX *)becli, be_client_destructor);
    2172             : 
    2173           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Added Frontend client [%s]\n", cli_name);
    2174             : 
    2175             :     /* reply that all is ok */
    2176           0 :     ret = sbus_request_return_and_finish(dbus_req,
    2177             :                                          DBUS_TYPE_UINT16, &version,
    2178             :                                          DBUS_TYPE_INVALID);
    2179           0 :     if (ret != EOK) {
    2180           0 :         sbus_disconnect(conn);
    2181           0 :         return ret;
    2182             :     }
    2183             : 
    2184           0 :     becli->initialized = true;
    2185           0 :     return EOK;
    2186             : }
    2187             : 
    2188           0 : static errno_t be_file_check_online_request(struct be_req *req)
    2189             : {
    2190             :     int ret;
    2191             : 
    2192           0 :     req->be_ctx->offstat.went_offline = time(NULL);
    2193           0 :     reset_fo(req->be_ctx);
    2194             : 
    2195           0 :     ret = be_file_request(req->be_ctx, req,
    2196           0 :                           req->be_ctx->bet_info[BET_ID].bet_ops->check_online);
    2197           0 :     if (ret != EOK) {
    2198           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "be_file_request failed.\n");
    2199             :     }
    2200             : 
    2201           0 :     return ret;
    2202             : }
    2203             : 
    2204           0 : static void check_online_callback(struct be_req *req, int dp_err_type,
    2205             :                                   int errnum, const char *errstr)
    2206             : {
    2207             :     int ret;
    2208             : 
    2209           0 :     DEBUG(SSSDBG_CONF_SETTINGS, "Backend returned: (%d, %d, %s) [%s]\n",
    2210             :               dp_err_type, errnum, errstr?errstr:"<NULL>",
    2211             :               dp_pam_err_to_string(req, dp_err_type, errnum));
    2212             : 
    2213           0 :     req->be_ctx->check_online_ref_count--;
    2214             : 
    2215           0 :     if (dp_err_type != DP_ERR_OK && req->be_ctx->check_online_ref_count > 0) {
    2216           0 :         ret = be_file_check_online_request(req);
    2217           0 :         if (ret != EOK) {
    2218           0 :             DEBUG(SSSDBG_CRIT_FAILURE,
    2219             :                   "be_file_check_online_request failed.\n");
    2220           0 :             goto done;
    2221             :         }
    2222           0 :         return;
    2223             :     }
    2224             : 
    2225             : done:
    2226           0 :     req->be_ctx->check_online_ref_count = 0;
    2227           0 :     if (dp_err_type != DP_ERR_OFFLINE) {
    2228           0 :         if (dp_err_type != DP_ERR_OK) {
    2229           0 :             reset_fo(req->be_ctx);
    2230             :         }
    2231           0 :         be_reset_offline(req->be_ctx);
    2232             :     }
    2233             : 
    2234           0 :     talloc_free(req);
    2235             : 
    2236           0 :     return;
    2237             : }
    2238             : 
    2239           0 : static void check_if_online(struct be_ctx *ctx)
    2240             : {
    2241             :     int ret;
    2242           0 :     struct be_req *be_req = NULL;
    2243             : 
    2244           0 :     be_run_unconditional_online_cb(ctx);
    2245             : 
    2246           0 :     if (ctx->offstat.offline == false) {
    2247           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    2248             :               "Backend is already online, nothing to do.\n");
    2249           0 :         return;
    2250             :     }
    2251             : 
    2252             :     /* Make sure nobody tries to go online while we are checking */
    2253           0 :     ctx->offstat.went_offline = time(NULL);
    2254             : 
    2255           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Trying to go back online!\n");
    2256             : 
    2257           0 :     ctx->check_online_ref_count++;
    2258             : 
    2259           0 :     if (ctx->check_online_ref_count != 1) {
    2260           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    2261             :               "There is an online check already running.\n");
    2262           0 :         return;
    2263             :     }
    2264             : 
    2265           0 :     if (ctx->bet_info[BET_ID].bet_ops->check_online == NULL) {
    2266           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    2267             :               "ID providers does not provide a check_online method.\n");
    2268           0 :         goto failed;
    2269             :     }
    2270             : 
    2271           0 :     be_req = be_req_create(ctx, NULL, ctx,
    2272             :                            check_online_callback, NULL);
    2273           0 :     if (be_req == NULL) {
    2274           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
    2275           0 :         goto failed;
    2276             :     }
    2277             : 
    2278           0 :     ret = be_file_check_online_request(be_req);
    2279           0 :     if (ret != EOK) {
    2280           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "be_file_check_online_request failed.\n");
    2281           0 :         goto failed;
    2282             :     }
    2283             : 
    2284           0 :     return;
    2285             : 
    2286             : failed:
    2287           0 :     ctx->check_online_ref_count--;
    2288           0 :     DEBUG(SSSDBG_CRIT_FAILURE, "Failed to run a check_online test.\n");
    2289             : 
    2290           0 :     talloc_free(be_req);
    2291             : 
    2292           0 :     if (ctx->check_online_ref_count == 0) {
    2293           0 :         reset_fo(ctx);
    2294           0 :         be_reset_offline(ctx);
    2295             :     }
    2296             : 
    2297           0 :     return;
    2298             : }
    2299             : 
    2300           0 : static void init_timeout(struct tevent_context *ev,
    2301             :                          struct tevent_timer *te,
    2302             :                          struct timeval t, void *ptr)
    2303             : {
    2304             :     struct be_client *becli;
    2305             : 
    2306           0 :     DEBUG(SSSDBG_OP_FAILURE,
    2307             :           "Client timed out before Identification [%p]!\n", te);
    2308             : 
    2309           0 :     becli = talloc_get_type(ptr, struct be_client);
    2310             : 
    2311           0 :     sbus_disconnect(becli->conn);
    2312           0 :     talloc_zfree(becli);
    2313           0 : }
    2314             : 
    2315           0 : static int be_client_init(struct sbus_connection *conn, void *data)
    2316             : {
    2317             :     struct be_ctx *bectx;
    2318             :     struct be_client *becli;
    2319             :     struct timeval tv;
    2320             : 
    2321           0 :     bectx = talloc_get_type(data, struct be_ctx);
    2322             : 
    2323             :     /* hang off this memory to the connection so that when the connection
    2324             :      * is freed we can potentially call a destructor */
    2325             : 
    2326           0 :     becli = talloc(conn, struct be_client);
    2327           0 :     if (!becli) {
    2328           0 :         DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
    2329           0 :         talloc_zfree(conn);
    2330           0 :         return ENOMEM;
    2331             :     }
    2332           0 :     becli->bectx = bectx;
    2333           0 :     becli->conn = conn;
    2334           0 :     becli->initialized = false;
    2335             : 
    2336             :     /* Allow access from the SSSD user */
    2337           0 :     sbus_allow_uid(conn, &bectx->uid);
    2338             : 
    2339             :     /* 5 seconds should be plenty */
    2340           0 :     tv = tevent_timeval_current_ofs(5, 0);
    2341             : 
    2342           0 :     becli->timeout = tevent_add_timer(bectx->ev, becli,
    2343             :                                       tv, init_timeout, becli);
    2344           0 :     if (!becli->timeout) {
    2345           0 :         DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
    2346           0 :         talloc_zfree(conn);
    2347           0 :         return ENOMEM;
    2348             :     }
    2349           0 :     DEBUG(SSSDBG_CONF_SETTINGS,
    2350             :           "Set-up Backend ID timeout [%p]\n", becli->timeout);
    2351             : 
    2352           0 :     return sbus_conn_register_iface(conn, &be_methods.vtable, DP_PATH, becli);
    2353             : }
    2354             : 
    2355             : /* be_srv_init
    2356             :  * set up per-domain sbus channel */
    2357           0 : static int be_srv_init(struct be_ctx *ctx,
    2358             :                        uid_t uid, gid_t gid)
    2359             : {
    2360             :     char *sbus_address;
    2361             :     int ret;
    2362             : 
    2363             :     /* Set up SBUS connection to the monitor */
    2364           0 :     ret = dp_get_sbus_address(ctx, &sbus_address, ctx->domain->name);
    2365           0 :     if (ret != EOK) {
    2366           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Could not get sbus backend address.\n");
    2367           0 :         return ret;
    2368             :     }
    2369             : 
    2370           0 :     ctx->uid = uid;
    2371           0 :     ctx->gid = gid;
    2372             : 
    2373           0 :     ret = sbus_new_server(ctx, ctx->ev, sbus_address, uid, gid,
    2374             :                           true, &ctx->sbus_srv, be_client_init, ctx);
    2375           0 :     if (ret != EOK) {
    2376           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set up sbus server.\n");
    2377           0 :         return ret;
    2378             :     }
    2379             : 
    2380           0 :     return EOK;
    2381             : }
    2382             : 
    2383           0 : static void be_target_access_permit(struct be_req *be_req)
    2384             : {
    2385           0 :     struct pam_data *pd =
    2386           0 :                     talloc_get_type(be_req_get_data(be_req), struct pam_data);
    2387           0 :     DEBUG(SSSDBG_TRACE_ALL,
    2388             :           "be_target_access_permit called, returning PAM_SUCCESS.\n");
    2389             : 
    2390           0 :     pd->pam_status = PAM_SUCCESS;
    2391           0 :     be_req_terminate(be_req, DP_ERR_OK, PAM_SUCCESS, NULL);
    2392           0 : }
    2393             : 
    2394             : static struct bet_ops be_target_access_permit_ops = {
    2395             :     .check_online = NULL,
    2396             :     .handler = be_target_access_permit,
    2397             :     .finalize = NULL
    2398             : };
    2399             : 
    2400           0 : static void be_target_access_deny(struct be_req *be_req)
    2401             : {
    2402           0 :     struct pam_data *pd =
    2403           0 :                     talloc_get_type(be_req_get_data(be_req), struct pam_data);
    2404           0 :     DEBUG(SSSDBG_TRACE_ALL,
    2405             :           "be_target_access_deny called, returning PAM_PERM_DENIED.\n");
    2406             : 
    2407           0 :     pd->pam_status = PAM_PERM_DENIED;
    2408           0 :     be_req_terminate(be_req, DP_ERR_OK, PAM_PERM_DENIED, NULL);
    2409           0 : }
    2410             : 
    2411             : static struct bet_ops be_target_access_deny_ops = {
    2412             :     .check_online = NULL,
    2413             :     .handler = be_target_access_deny,
    2414             :     .finalize = NULL
    2415             : };
    2416             : 
    2417           0 : static int load_backend_module(struct be_ctx *ctx,
    2418             :                                enum bet_type bet_type,
    2419             :                                struct bet_info *bet_info,
    2420             :                                const char *default_mod_name)
    2421             : {
    2422             :     TALLOC_CTX *tmp_ctx;
    2423           0 :     int ret = EINVAL;
    2424           0 :     bool already_loaded = false;
    2425           0 :     int lb=0;
    2426           0 :     char *mod_name = NULL;
    2427           0 :     char *path = NULL;
    2428             :     void *handle;
    2429           0 :     char *mod_init_fn_name = NULL;
    2430           0 :     bet_init_fn_t mod_init_fn = NULL;
    2431             : 
    2432           0 :     (*bet_info).bet_type = bet_type;
    2433           0 :     (*bet_info).mod_name = NULL;
    2434           0 :     (*bet_info).bet_ops = NULL;
    2435           0 :     (*bet_info).pvt_bet_data = NULL;
    2436             : 
    2437           0 :     if (bet_type <= BET_NULL || bet_type >= BET_MAX ||
    2438           0 :         bet_type != bet_data[bet_type].bet_type) {
    2439           0 :         DEBUG(SSSDBG_OP_FAILURE, "invalid bet_type or bet_data corrupted.\n");
    2440           0 :         return EINVAL;
    2441             :     }
    2442             : 
    2443           0 :     tmp_ctx = talloc_new(ctx);
    2444           0 :     if (!tmp_ctx) {
    2445           0 :         DEBUG(SSSDBG_TRACE_LIBS, "talloc_new failed.\n");
    2446           0 :         return ENOMEM;
    2447             :     }
    2448             : 
    2449           0 :     ret = confdb_get_string(ctx->cdb, tmp_ctx, ctx->conf_path,
    2450             :                             bet_data[bet_type].option_name, NULL,
    2451             :                             &mod_name);
    2452           0 :     if (ret != EOK) {
    2453           0 :         ret = EFAULT;
    2454           0 :         goto done;
    2455             :     }
    2456           0 :     if (!mod_name) {
    2457           0 :         if (default_mod_name != NULL) {
    2458           0 :             DEBUG(SSSDBG_FUNC_DATA,
    2459             :                   "no module name found in confdb, using [%s].\n",
    2460             :                       default_mod_name);
    2461           0 :             mod_name = talloc_strdup(ctx, default_mod_name);
    2462             :         } else {
    2463           0 :             ret = ENOENT;
    2464           0 :             goto done;
    2465             :         }
    2466             :     }
    2467             : 
    2468           0 :     if (strcasecmp(mod_name, NO_PROVIDER) == 0) {
    2469           0 :         ret = ENOENT;
    2470           0 :         goto done;
    2471             :     }
    2472             : 
    2473           0 :     if (bet_type == BET_ACCESS) {
    2474           0 :         if (strcmp(mod_name, ACCESS_PERMIT) == 0) {
    2475           0 :             (*bet_info).bet_ops = &be_target_access_permit_ops;
    2476           0 :             (*bet_info).pvt_bet_data = NULL;
    2477           0 :             (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_PERMIT);
    2478             : 
    2479           0 :             ret = EOK;
    2480           0 :             goto done;
    2481             :         }
    2482           0 :         if (strcmp(mod_name, ACCESS_DENY) == 0) {
    2483           0 :             (*bet_info).bet_ops = &be_target_access_deny_ops;
    2484           0 :             (*bet_info).pvt_bet_data = NULL;
    2485           0 :             (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_DENY);
    2486             : 
    2487           0 :             ret = EOK;
    2488           0 :             goto done;
    2489             :         }
    2490             :     }
    2491             : 
    2492           0 :     mod_init_fn_name = talloc_asprintf(tmp_ctx,
    2493             :                                        bet_data[bet_type].mod_init_fn_name_fmt,
    2494             :                                        mod_name);
    2495           0 :     if (mod_init_fn_name == NULL) {
    2496           0 :         DEBUG(SSSDBG_TRACE_LIBS, "talloc_asprintf failed\n");
    2497           0 :         ret = ENOMEM;
    2498           0 :         goto done;
    2499             :     }
    2500             : 
    2501             : 
    2502           0 :     lb = 0;
    2503           0 :     while(ctx->loaded_be[lb].be_name != NULL) {
    2504           0 :         if (strncmp(ctx->loaded_be[lb].be_name, mod_name,
    2505             :                     strlen(mod_name)) == 0) {
    2506           0 :             DEBUG(SSSDBG_TRACE_LIBS,
    2507             :                   "Backend [%s] already loaded.\n", mod_name);
    2508           0 :             already_loaded = true;
    2509           0 :             break;
    2510             :         }
    2511             : 
    2512           0 :         ++lb;
    2513           0 :         if (lb >= BET_MAX) {
    2514           0 :             DEBUG(SSSDBG_OP_FAILURE, "Backend context corrupted.\n");
    2515           0 :             ret = EINVAL;
    2516           0 :             goto done;
    2517             :         }
    2518             :     }
    2519             : 
    2520           0 :     if (!already_loaded) {
    2521           0 :         path = talloc_asprintf(tmp_ctx, "%s/libsss_%s.so",
    2522             :                                DATA_PROVIDER_PLUGINS_PATH, mod_name);
    2523           0 :         if (!path) {
    2524           0 :             ret = ENOMEM;
    2525           0 :             goto done;
    2526             :         }
    2527             : 
    2528           0 :         DEBUG(SSSDBG_TRACE_LIBS,
    2529             :               "Loading backend [%s] with path [%s].\n", mod_name, path);
    2530           0 :         handle = dlopen(path, RTLD_NOW);
    2531           0 :         if (!handle) {
    2532           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2533             :                   "Unable to load %s module with path (%s), error: %s\n",
    2534             :                       mod_name, path, dlerror());
    2535           0 :             ret = ELIBACC;
    2536           0 :             goto done;
    2537             :         }
    2538             : 
    2539           0 :         ctx->loaded_be[lb].be_name = talloc_strdup(ctx, mod_name);
    2540           0 :         ctx->loaded_be[lb].handle = handle;
    2541             :     }
    2542             : 
    2543           0 :     mod_init_fn = (bet_init_fn_t)dlsym(ctx->loaded_be[lb].handle,
    2544             :                                            mod_init_fn_name);
    2545           0 :     if (mod_init_fn == NULL) {
    2546           0 :         if (default_mod_name != NULL &&
    2547           0 :             strcmp(default_mod_name, mod_name) == 0 ) {
    2548             :             /* If the default is used and fails we indicate this to the caller
    2549             :              * by returning ENOENT. Ths way the caller can decide how to
    2550             :              * handle the different types of error conditions. */
    2551           0 :             ret = ENOENT;
    2552             :         } else {
    2553           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2554             :                   "Unable to load init fn %s from module %s, error: %s\n",
    2555             :                       mod_init_fn_name, mod_name, dlerror());
    2556           0 :             ret = ELIBBAD;
    2557             :         }
    2558           0 :         goto done;
    2559             :     }
    2560             : 
    2561           0 :     ret = mod_init_fn(ctx, &(*bet_info).bet_ops, &(*bet_info).pvt_bet_data);
    2562           0 :     if (ret != EOK) {
    2563           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
    2564             :               "Error (%d) in module (%s) initialization (%s)!\n",
    2565             :                   ret, mod_name, mod_init_fn_name);
    2566           0 :         goto done;
    2567             :     }
    2568             : 
    2569           0 :     (*bet_info).mod_name = talloc_strdup(ctx, mod_name);
    2570             : 
    2571           0 :     ret = EOK;
    2572             : 
    2573             : done:
    2574           0 :     talloc_free(tmp_ctx);
    2575           0 :     return ret;
    2576             : }
    2577             : 
    2578           0 : static void signal_be_offline(struct tevent_context *ev,
    2579             :                               struct tevent_signal *se,
    2580             :                               int signum,
    2581             :                               int count,
    2582             :                               void *siginfo,
    2583             :                               void *private_data)
    2584             : {
    2585           0 :     struct be_ctx *ctx = talloc_get_type(private_data, struct be_ctx);
    2586           0 :     be_mark_offline(ctx);
    2587           0 : }
    2588             : 
    2589           0 : static void signal_be_reset_offline(struct tevent_context *ev,
    2590             :                                     struct tevent_signal *se,
    2591             :                                     int signum,
    2592             :                                     int count,
    2593             :                                     void *siginfo,
    2594             :                                     void *private_data)
    2595             : {
    2596           0 :     struct be_ctx *ctx = talloc_get_type(private_data, struct be_ctx);
    2597           0 :     check_if_online(ctx);
    2598           0 : }
    2599             : 
    2600           0 : int be_process_init_sudo(struct be_ctx *be_ctx)
    2601             : {
    2602           0 :     TALLOC_CTX *tmp_ctx = NULL;
    2603           0 :     char **services = NULL;
    2604           0 :     char *provider = NULL;
    2605           0 :     bool responder_enabled = false;
    2606             :     int i;
    2607             :     int ret;
    2608             : 
    2609           0 :     tmp_ctx = talloc_new(NULL);
    2610           0 :     if (tmp_ctx == NULL) {
    2611           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
    2612           0 :         return ENOMEM;
    2613             :     }
    2614             : 
    2615           0 :     ret = confdb_get_string_as_list(be_ctx->cdb, tmp_ctx,
    2616             :                                     CONFDB_MONITOR_CONF_ENTRY,
    2617             :                                     CONFDB_MONITOR_ACTIVE_SERVICES, &services);
    2618           0 :     if (ret != EOK) {
    2619           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to read from confdb [%d]: %s\n",
    2620             :                                      ret, strerror(ret));
    2621           0 :         goto done;
    2622             :     }
    2623             : 
    2624           0 :     for (i = 0; services[i] != NULL; i++) {
    2625           0 :         if (strcmp(services[i], "sudo") == 0) {
    2626           0 :             responder_enabled = true;
    2627           0 :             break;
    2628             :         }
    2629             :     }
    2630             : 
    2631           0 :     ret = confdb_get_string(be_ctx->cdb, tmp_ctx, be_ctx->conf_path,
    2632             :                             CONFDB_DOMAIN_SUDO_PROVIDER, NULL, &provider);
    2633           0 :     if (ret != EOK) {
    2634           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to read from confdb [%d]: %s\n",
    2635             :                                      ret, strerror(ret));
    2636           0 :         goto done;
    2637             :     }
    2638             : 
    2639           0 :     if (!responder_enabled && provider == NULL) {
    2640             :         /* provider is not set explicitly */
    2641           0 :         DEBUG(SSSDBG_TRACE_FUNC,
    2642             :               "SUDO is not listed in services, disabling SUDO module.\n");
    2643           0 :         ret = ENOENT;
    2644           0 :         goto done;
    2645             :     }
    2646             : 
    2647           0 :     if (!responder_enabled && provider != NULL
    2648           0 :             && strcmp(provider, NO_PROVIDER) != 0) {
    2649             :         /* provider is set but responder is disabled */
    2650           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "SUDO provider is set, but it is not "
    2651             :               "listed in active services. SUDO support will not work!\n");
    2652             :     }
    2653             : 
    2654           0 :     ret = load_backend_module(be_ctx, BET_SUDO, &be_ctx->bet_info[BET_SUDO],
    2655           0 :                               be_ctx->bet_info[BET_ID].mod_name);
    2656             : 
    2657             : done:
    2658           0 :     talloc_free(tmp_ctx);
    2659           0 :     return ret;
    2660             : }
    2661             : 
    2662           0 : int be_process_init(TALLOC_CTX *mem_ctx,
    2663             :                     const char *be_domain,
    2664             :                     uid_t uid, gid_t gid,
    2665             :                     struct tevent_context *ev,
    2666             :                     struct confdb_ctx *cdb)
    2667             : {
    2668             :     struct be_ctx *ctx;
    2669             :     struct tevent_signal *tes;
    2670             :     int ret;
    2671             : 
    2672           0 :     ctx = talloc_zero(mem_ctx, struct be_ctx);
    2673           0 :     if (!ctx) {
    2674           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing be_ctx\n");
    2675           0 :         return ENOMEM;
    2676             :     }
    2677           0 :     ctx->ev = ev;
    2678           0 :     ctx->cdb = cdb;
    2679           0 :     ctx->identity = talloc_asprintf(ctx, "%%BE_%s", be_domain);
    2680           0 :     ctx->conf_path = talloc_asprintf(ctx, CONFDB_DOMAIN_PATH_TMPL, be_domain);
    2681           0 :     if (!ctx->identity || !ctx->conf_path) {
    2682           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!?\n");
    2683           0 :         ret = ENOMEM;
    2684           0 :         goto fail;
    2685             :     }
    2686             : 
    2687           0 :     ret = be_init_failover(ctx);
    2688           0 :     if (ret != EOK) {
    2689           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
    2690             :               "fatal error initializing failover context\n");
    2691           0 :         goto fail;
    2692             :     }
    2693             : 
    2694           0 :     ret = sssd_domain_init(ctx, cdb, be_domain, DB_PATH, &ctx->domain);
    2695           0 :     if (ret != EOK) {
    2696           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error opening cache database\n");
    2697           0 :         goto fail;
    2698             :     }
    2699             : 
    2700           0 :     ret = sss_monitor_init(ctx, ctx->ev, &monitor_be_methods,
    2701             :                            ctx->identity, DATA_PROVIDER_VERSION,
    2702             :                            ctx, &ctx->mon_conn);
    2703           0 :     if (ret != EOK) {
    2704           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
    2705             :               "fatal error setting up monitor bus\n");
    2706           0 :         goto fail;
    2707             :     }
    2708             : 
    2709             :     /* We need this for subdomains support, as they have to store fully
    2710             :      * qualified user and group names for now */
    2711           0 :     ret = sss_names_init(ctx->domain, cdb,
    2712           0 :                          ctx->domain->name, &ctx->domain->names);
    2713           0 :     if (ret != EOK) {
    2714           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
    2715             :               "fatal error setting fully qualified name format for %s\n",
    2716             :               ctx->domain->name);
    2717           0 :         goto fail;
    2718             :     }
    2719             : 
    2720           0 :     ret = be_srv_init(ctx, uid, gid);
    2721           0 :     if (ret != EOK) {
    2722           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up server bus\n");
    2723           0 :         goto fail;
    2724             :     }
    2725             : 
    2726             :     /* Initialize be_refresh periodic task. */
    2727           0 :     ctx->refresh_ctx = be_refresh_ctx_init(ctx);
    2728           0 :     if (ctx->refresh_ctx == NULL) {
    2729           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Unable to initialize refresh_ctx\n");
    2730           0 :         ret = ENOMEM;
    2731           0 :         goto fail;
    2732             :     }
    2733             : 
    2734           0 :     if (ctx->domain->refresh_expired_interval > 0) {
    2735           0 :         ret = be_ptask_create(ctx, ctx, ctx->domain->refresh_expired_interval,
    2736           0 :                               30, 5, 0, ctx->domain->refresh_expired_interval,
    2737             :                               BE_PTASK_OFFLINE_SKIP, 0,
    2738             :                               be_refresh_send, be_refresh_recv,
    2739           0 :                               ctx->refresh_ctx, "Refresh Records", NULL);
    2740           0 :         if (ret != EOK) {
    2741           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2742             :                   "Unable to initialize refresh periodic task\n");
    2743           0 :             goto fail;
    2744             :         }
    2745             :     }
    2746             : 
    2747           0 :     ret = load_backend_module(ctx, BET_ID,
    2748             :                               &ctx->bet_info[BET_ID], NULL);
    2749           0 :     if (ret != EOK) {
    2750           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
    2751             :               "fatal error initializing data providers\n");
    2752           0 :         goto fail;
    2753             :     }
    2754           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
    2755             :           "ID backend target successfully loaded from provider [%s].\n",
    2756             :           ctx->bet_info[BET_ID].mod_name);
    2757             : 
    2758           0 :     ret = load_backend_module(ctx, BET_AUTH,
    2759             :                               &ctx->bet_info[BET_AUTH],
    2760           0 :                               ctx->bet_info[BET_ID].mod_name);
    2761           0 :     if (ret != EOK) {
    2762           0 :         if (ret != ENOENT) {
    2763           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2764             :                   "fatal error initializing data providers\n");
    2765           0 :             goto fail;
    2766             :         }
    2767           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    2768             :               "No authentication module provided for [%s] !!\n",
    2769             :               be_domain);
    2770             :     } else {
    2771           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    2772             :               "AUTH backend target successfully loaded "
    2773             :                "from provider [%s].\n", ctx->bet_info[BET_AUTH].mod_name);
    2774             :     }
    2775             : 
    2776           0 :     ret = load_backend_module(ctx, BET_ACCESS, &ctx->bet_info[BET_ACCESS],
    2777             :                               ACCESS_PERMIT);
    2778           0 :     if (ret != EOK) {
    2779           0 :         DEBUG(SSSDBG_FATAL_FAILURE,
    2780             :               "Failed to setup ACCESS backend.\n");
    2781           0 :         goto fail;
    2782             :     }
    2783           0 :     DEBUG(SSSDBG_TRACE_INTERNAL,
    2784             :           "ACCESS backend target successfully loaded "
    2785             :            "from provider [%s].\n", ctx->bet_info[BET_ACCESS].mod_name);
    2786             : 
    2787           0 :     ret = load_backend_module(ctx, BET_CHPASS,
    2788             :                               &ctx->bet_info[BET_CHPASS],
    2789           0 :                               ctx->bet_info[BET_AUTH].mod_name);
    2790           0 :     if (ret != EOK) {
    2791           0 :         if (ret != ENOENT) {
    2792           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2793             :                   "fatal error initializing data providers\n");
    2794           0 :             goto fail;
    2795             :         }
    2796           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    2797             :               "No change password module provided for [%s] !!\n",
    2798             :                be_domain);
    2799             :     } else {
    2800           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    2801             :               "CHPASS backend target successfully loaded "
    2802             :                "from provider [%s].\n", ctx->bet_info[BET_CHPASS].mod_name);
    2803             :     }
    2804             : 
    2805           0 :     ret = be_process_init_sudo(ctx);
    2806           0 :     if (ret != EOK) {
    2807           0 :         if (ret != ENOENT) {
    2808           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2809             :                   "fatal error initializing data providers\n");
    2810           0 :             goto fail;
    2811             :         }
    2812           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    2813             :               "No SUDO module provided for [%s] !!\n", be_domain);
    2814             :     } else {
    2815           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    2816             :               "SUDO backend target successfully loaded "
    2817             :                "from provider [%s].\n", ctx->bet_info[BET_SUDO].mod_name);
    2818             :     }
    2819             : 
    2820           0 :     ret = load_backend_module(ctx, BET_AUTOFS,
    2821             :                               &ctx->bet_info[BET_AUTOFS],
    2822           0 :                               ctx->bet_info[BET_ID].mod_name);
    2823           0 :     if (ret != EOK) {
    2824           0 :         if (ret != ENOENT) {
    2825           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2826             :                   "fatal error initializing data providers\n");
    2827           0 :             goto fail;
    2828             :         }
    2829           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    2830             :               "No autofs module provided for [%s] !!\n", be_domain);
    2831             :     } else {
    2832           0 :         DEBUG(SSSDBG_TRACE_INTERNAL,
    2833             :               "autofs backend target successfully loaded "
    2834             :                "from provider [%s].\n", ctx->bet_info[BET_AUTOFS].mod_name);
    2835             :     }
    2836             : 
    2837           0 :     ret = load_backend_module(ctx, BET_SELINUX,
    2838             :                               &ctx->bet_info[BET_SELINUX],
    2839           0 :                               ctx->bet_info[BET_ID].mod_name);
    2840           0 :     if (ret != EOK) {
    2841           0 :         if (ret != ENOENT) {
    2842           0 :             DEBUG(SSSDBG_FATAL_FAILURE, "fatal error initializing data providers\n");
    2843           0 :             goto fail;
    2844             :         }
    2845           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "No selinux module provided for [%s] !!\n",
    2846             :                   be_domain);
    2847             :     } else {
    2848           0 :         DEBUG(SSSDBG_TRACE_ALL, "selinux backend target successfully loaded "
    2849             :                   "from provider [%s].\n", ctx->bet_info[BET_SELINUX].mod_name);
    2850             :     }
    2851             : 
    2852           0 :     ret = load_backend_module(ctx, BET_HOSTID,
    2853             :                               &ctx->bet_info[BET_HOSTID],
    2854           0 :                               ctx->bet_info[BET_ID].mod_name);
    2855           0 :     if (ret != EOK) {
    2856           0 :         if (ret != ENOENT) {
    2857           0 :             DEBUG(SSSDBG_FATAL_FAILURE,
    2858             :                   "fatal error initializing data providers\n");
    2859           0 :             goto fail;
    2860             :         }
    2861           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
    2862             :               "No host info module provided for [%s] !!\n", be_domain);
    2863             :     } else {
    2864           0 :         DEBUG(SSSDBG_TRACE_ALL,
    2865             :               "HOST backend target successfully loaded from provider [%s].\n",
    2866             :                ctx->bet_info[BET_HOSTID].mod_name);
    2867             :     }
    2868             : 
    2869           0 :     ret = load_backend_module(ctx, BET_SUBDOMAINS,
    2870             :                               &ctx->bet_info[BET_SUBDOMAINS],
    2871           0 :                               ctx->bet_info[BET_ID].mod_name);
    2872           0 :     if (ret != EOK) {
    2873           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Subdomains are not supported for [%s] !!\n", be_domain);
    2874             :     } else {
    2875           0 :         DEBUG(SSSDBG_TRACE_ALL, "Get-Subdomains backend target successfully loaded "
    2876             :                   "from provider [%s].\n",
    2877             :                   ctx->bet_info[BET_SUBDOMAINS].mod_name);
    2878             :     }
    2879             : 
    2880             :     /* Handle SIGUSR1 to force offline behavior */
    2881           0 :     BlockSignals(false, SIGUSR1);
    2882           0 :     tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
    2883             :                             signal_be_offline, ctx);
    2884           0 :     if (tes == NULL) {
    2885           0 :         ret = EIO;
    2886           0 :         goto fail;
    2887             :     }
    2888             : 
    2889             :     /* Handle SIGUSR2 to force going online */
    2890           0 :     BlockSignals(false, SIGUSR2);
    2891           0 :     tes = tevent_add_signal(ctx->ev, ctx, SIGUSR2, 0,
    2892             :                             signal_be_reset_offline, ctx);
    2893           0 :     if (tes == NULL) {
    2894           0 :         ret = EIO;
    2895           0 :         goto fail;
    2896             :     }
    2897             : 
    2898           0 :     return EOK;
    2899             : 
    2900             : fail:
    2901           0 :     talloc_free(ctx);
    2902           0 :     return ret;
    2903             : }
    2904             : 
    2905             : #ifndef UNIT_TESTING
    2906           0 : int main(int argc, const char *argv[])
    2907             : {
    2908             :     int opt;
    2909             :     poptContext pc;
    2910           0 :     char *be_domain = NULL;
    2911           0 :     char *srv_name = NULL;
    2912             :     struct main_context *main_ctx;
    2913             :     char *confdb_path;
    2914             :     int ret;
    2915             :     uid_t uid;
    2916             :     gid_t gid;
    2917             : 
    2918           0 :     struct poptOption long_options[] = {
    2919             :         POPT_AUTOHELP
    2920           0 :         SSSD_MAIN_OPTS
    2921           0 :         SSSD_SERVER_OPTS(uid, gid)
    2922             :         {"domain", 0, POPT_ARG_STRING, &be_domain, 0,
    2923           0 :          _("Domain of the information provider (mandatory)"), NULL },
    2924             :         POPT_TABLEEND
    2925             :     };
    2926             : 
    2927             :     /* Set debug level to invalid value so we can deside if -d 0 was used. */
    2928           0 :     debug_level = SSSDBG_INVALID;
    2929             : 
    2930           0 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
    2931           0 :     while((opt = poptGetNextOpt(pc)) != -1) {
    2932             :         switch(opt) {
    2933             :         default:
    2934           0 :         fprintf(stderr, "\nInvalid option %s: %s\n\n",
    2935             :                   poptBadOption(pc, 0), poptStrerror(opt));
    2936           0 :             poptPrintUsage(pc, stderr, 0);
    2937           0 :             return 1;
    2938             :         }
    2939             :     }
    2940             : 
    2941           0 :     if (be_domain == NULL) {
    2942           0 :         fprintf(stderr, "\nMissing option, --domain is a mandatory option.\n\n");
    2943           0 :             poptPrintUsage(pc, stderr, 0);
    2944           0 :             return 1;
    2945             :     }
    2946             : 
    2947           0 :     poptFreeContext(pc);
    2948             : 
    2949           0 :     DEBUG_INIT(debug_level);
    2950             : 
    2951             :     /* set up things like debug , signals, daemonization, etc... */
    2952           0 :     debug_log_file = talloc_asprintf(NULL, "sssd_%s", be_domain);
    2953           0 :     if (!debug_log_file) return 2;
    2954             : 
    2955           0 :     srv_name = talloc_asprintf(NULL, "sssd[be[%s]]", be_domain);
    2956           0 :     if (!srv_name) return 2;
    2957             : 
    2958           0 :     confdb_path = talloc_asprintf(NULL, CONFDB_DOMAIN_PATH_TMPL, be_domain);
    2959           0 :     if (!confdb_path) return 2;
    2960             : 
    2961           0 :     ret = server_setup(srv_name, 0, 0, 0, confdb_path, &main_ctx);
    2962           0 :     if (ret != EOK) {
    2963           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Could not set up mainloop [%d]\n", ret);
    2964           0 :         return 2;
    2965             :     }
    2966             : 
    2967           0 :     ret = setenv(SSS_DOM_ENV, be_domain, 1);
    2968           0 :     if (ret != 0) {
    2969           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Setting "SSS_DOM_ENV" failed, journald "
    2970             :               "logging mightnot work as expected\n");
    2971             :     }
    2972             : 
    2973           0 :     ret = die_if_parent_died();
    2974           0 :     if (ret != EOK) {
    2975             :         /* This is not fatal, don't return */
    2976           0 :         DEBUG(SSSDBG_OP_FAILURE,
    2977             :               "Could not set up to exit when parent process does\n");
    2978             :     }
    2979             : 
    2980           0 :     ret = be_process_init(main_ctx,
    2981             :                           be_domain, uid, gid,
    2982           0 :                           main_ctx->event_ctx,
    2983           0 :                           main_ctx->confdb_ctx);
    2984           0 :     if (ret != EOK) {
    2985           0 :         DEBUG(SSSDBG_FATAL_FAILURE, "Could not initialize backend [%d]\n", ret);
    2986           0 :         return 3;
    2987             :     }
    2988             : 
    2989           0 :     ret = chown_debug_file(NULL, uid, gid);
    2990           0 :     if (ret != EOK) {
    2991           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
    2992             :               "Cannot chown the debug files, debugging might not work!\n");
    2993             :     }
    2994             : 
    2995           0 :     ret = become_user(uid, gid);
    2996           0 :     if (ret != EOK) {
    2997           0 :         DEBUG(SSSDBG_FUNC_DATA,
    2998             :               "Cannot become user [%"SPRIuid"][%"SPRIgid"].\n", uid, gid);
    2999           0 :         return ret;
    3000             :     }
    3001             : 
    3002           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Backend provider (%s) started!\n", be_domain);
    3003             : 
    3004             :     /* loop on main */
    3005           0 :     server_loop(main_ctx);
    3006             : 
    3007           0 :     return 0;
    3008             : }
    3009             : #endif
    3010             : 
    3011           0 : static int data_provider_res_init(struct sbus_request *dbus_req, void *data)
    3012             : {
    3013             :     struct be_ctx *be_ctx;
    3014           0 :     be_ctx = talloc_get_type(data, struct be_ctx);
    3015             : 
    3016           0 :     resolv_reread_configuration(be_ctx->be_res->resolv);
    3017           0 :     check_if_online(be_ctx);
    3018             : 
    3019           0 :     return monitor_common_res_init(dbus_req, data);
    3020             : }
    3021             : 
    3022           0 : static int data_provider_go_offline(struct sbus_request *dbus_req, void *data)
    3023             : {
    3024             :     struct be_ctx *be_ctx;
    3025           0 :     be_ctx = talloc_get_type(data, struct be_ctx);
    3026           0 :     be_mark_offline(be_ctx);
    3027           0 :     return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
    3028             : }
    3029             : 
    3030           0 : static int data_provider_reset_offline(struct sbus_request *dbus_req, void *data)
    3031             : {
    3032             :     struct be_ctx *be_ctx;
    3033           0 :     be_ctx = talloc_get_type(data, struct be_ctx);
    3034           0 :     check_if_online(be_ctx);
    3035           0 :     return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
    3036             : }
    3037             : 
    3038           0 : static int data_provider_logrotate(struct sbus_request *dbus_req, void *data)
    3039             : {
    3040             :     errno_t ret;
    3041           0 :     struct be_ctx *be_ctx = talloc_get_type(data, struct be_ctx);
    3042             : 
    3043           0 :     ret = server_common_rotate_logs(be_ctx->cdb, be_ctx->conf_path);
    3044           0 :     if (ret != EOK) return ret;
    3045             : 
    3046           0 :     return sbus_request_return_and_finish(dbus_req, DBUS_TYPE_INVALID);
    3047             : }

Generated by: LCOV version 1.10