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 : }
|