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
34 #include <security/pam_appl.h>
35 #include <security/pam_modules.h>
36
37 #include "popt.h"
38 #include "util/util.h"
39 #include "confdb/confdb.h"
40 #include "db/sysdb.h"
41 #include "dbus/dbus.h"
42 #include "sbus/sssd_dbus.h"
43 #include "providers/dp_backend.h"
44 #include "providers/fail_over.h"
45 #include "resolv/async_resolv.h"
46 #include "monitor/monitor_interfaces.h"
47
48 #define MSG_TARGET_NO_CONFIGURED "sssd_be: The requested target is not configured"
49
50 #define ACCESS_PERMIT "permit"
51 #define ACCESS_DENY "deny"
52 #define NO_PROVIDER "none"
53
54 static int data_provider_res_init(DBusMessage *message,
55 struct sbus_connection *conn);
56 static int data_provider_go_offline(DBusMessage *message,
57 struct sbus_connection *conn);
58
59 struct sbus_method monitor_be_methods[] = {
60 { MON_CLI_METHOD_PING, monitor_common_pong },
61 { MON_CLI_METHOD_RES_INIT, data_provider_res_init },
62 { MON_CLI_METHOD_OFFLINE, data_provider_go_offline },
63 { MON_CLI_METHOD_ROTATE, monitor_common_rotate_logs },
64 { NULL, NULL }
65 };
66
67 struct sbus_interface monitor_be_interface = {
68 MONITOR_INTERFACE,
69 MONITOR_PATH,
70 SBUS_DEFAULT_VTABLE,
71 monitor_be_methods,
72 NULL
73 };
74
75 static int client_registration(DBusMessage *message, struct sbus_connection *conn);
76 static int be_check_online(DBusMessage *message, struct sbus_connection *conn);
77 static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn);
78 static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn);
79
80 struct sbus_method be_methods[] = {
81 { DP_METHOD_REGISTER, client_registration },
82 { DP_METHOD_ONLINE, be_check_online },
83 { DP_METHOD_GETACCTINFO, be_get_account_info },
84 { DP_METHOD_PAMHANDLER, be_pam_handler },
85 { NULL, NULL }
86 };
87
88 struct sbus_interface be_interface = {
89 DP_INTERFACE,
90 DP_PATH,
91 SBUS_DEFAULT_VTABLE,
92 be_methods,
93 NULL
94 };
95
96 static struct bet_data bet_data[] = {
97 {BET_NULL, NULL, NULL},
98 {BET_ID, CONFDB_DOMAIN_ID_PROVIDER, "sssm_%s_id_init"},
99 {BET_AUTH, CONFDB_DOMAIN_AUTH_PROVIDER, "sssm_%s_auth_init"},
100 {BET_ACCESS, CONFDB_DOMAIN_ACCESS_PROVIDER, "sssm_%s_access_init"},
101 {BET_CHPASS, CONFDB_DOMAIN_CHPASS_PROVIDER, "sssm_%s_chpass_init"},
102 {BET_MAX, NULL, NULL}
103 };
104
105 struct be_async_req {
106 be_req_fn_t fn;
107 struct be_req *req;
108 };
109
110 static void be_async_req_handler(struct tevent_context *ev,
111 struct tevent_timer *te,
112 struct timeval tv, void *pvt)
113 {
114 struct be_async_req *async_req;
115
116 async_req = talloc_get_type(pvt, struct be_async_req);
117
118 async_req->fn(async_req->req);
119 }
120
121 static int be_file_request(struct be_ctx *ctx,
122 be_req_fn_t fn,
123 struct be_req *req)
124 {
125 struct be_async_req *areq;
126 struct tevent_timer *te;
127 struct timeval tv;
128
129 if (!fn || !req) return EINVAL;
130
131 areq = talloc(req, struct be_async_req);
132 if (!areq) {
133 return ENOMEM;
134 }
135 areq->fn = fn;
136 areq->req = req;
137
138 /* fire immediately */
139 tv.tv_sec = 0;
140 tv.tv_usec = 0;
141
142 te = tevent_add_timer(ctx->ev, req, tv, be_async_req_handler, areq);
143 if (te == NULL) {
144 return EIO;
145 }
146
147 return EOK;
148 }
149
150 bool be_is_offline(struct be_ctx *ctx)
151 {
152 time_t now = time(NULL);
153
154 /* check if we are past the offline blackout timeout */
155 /* FIXME: get offline_timeout from configuration */
156 if (ctx->offstat.went_offline + 60 < now) {
157 ctx->offstat.offline = false;
158 }
159
160 return ctx->offstat.offline;
161 }
162
163 void be_mark_offline(struct be_ctx *ctx)
164 {
165 DEBUG(8, ("Going offline!\n"));
166
167 ctx->offstat.went_offline = time(NULL);
168 ctx->offstat.offline = true;
169 ctx->run_online_cb = true;
170 be_run_offline_cb(ctx);
171 }
172
173 static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
174 {
175 struct be_client *becli;
176 DBusMessage *reply;
177 DBusConnection *dbus_conn;
178 dbus_bool_t dbret;
179 void *user_data;
180 dbus_uint16_t online;
181 dbus_uint16_t err_maj = 0;
182 dbus_uint32_t err_min = 0;
183 static const char *err_msg = "Success";
184
185 user_data = sbus_conn_get_private_data(conn);
186 if (!user_data) return EINVAL;
187 becli = talloc_get_type(user_data, struct be_client);
188 if (!becli) return EINVAL;
189
190 reply = dbus_message_new_method_return(message);
191 if (!reply) return ENOMEM;
192
193 if (be_is_offline(becli->bectx)) {
194 online = MOD_OFFLINE;
195 } else {
196 online = MOD_ONLINE;
197 }
198
199 dbret = dbus_message_append_args(reply,
200 DBUS_TYPE_UINT16, &online,
201 DBUS_TYPE_UINT16, &err_maj,
202 DBUS_TYPE_UINT32, &err_min,
203 DBUS_TYPE_STRING, &err_msg,
204 DBUS_TYPE_INVALID);
205 if (!dbret) {
206 DEBUG(1, ("Failed to generate dbus reply\n"));
207 return EIO;
208 }
209
210 dbus_conn = sbus_get_connection(becli->conn);
211 dbus_connection_send(dbus_conn, reply, NULL);
212 dbus_message_unref(reply);
213
214 DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
215 err_maj, err_min, err_msg));
216
217 return EOK;
218 }
219
220 static char *dp_err_to_string(TALLOC_CTX *memctx, int dp_err_type, int errnum)
221 {
222 switch (dp_err_type) {
223 case DP_ERR_OK:
224 return talloc_strdup(memctx, "Success");
225 break;
226
227 case DP_ERR_OFFLINE:
228 return talloc_asprintf(memctx,
229 "Provider is Offline (%s)",
230 strerror(errnum));
231 break;
232
233 case DP_ERR_TIMEOUT:
234 return talloc_asprintf(memctx,
235 "Request timed out (%s)",
236 strerror(errnum));
237 break;
238
239 case DP_ERR_FATAL:
240 default:
241 return talloc_asprintf(memctx,
242 "Internal Error (%s)",
243 strerror(errnum));
244 break;
245 }
246
247 return NULL;
248 }
249
250
251 static void acctinfo_callback(struct be_req *req,
252 int dp_err_type,
253 int errnum,
254 const char *errstr)
255 {
256 DBusMessage *reply;
257 DBusConnection *dbus_conn;
258 dbus_bool_t dbret;
259 dbus_uint16_t err_maj = 0;
260 dbus_uint32_t err_min = 0;
261 const char *err_msg = NULL;
262
263 reply = (DBusMessage *)req->pvt;
264
265 if (reply) {
266 /* Return a reply if one was requested
267 * There may not be one if this request began
268 * while we were offline
269 */
270
271 err_maj = dp_err_type;
272 err_min = errnum;
273 if (errstr) {
274 err_msg = errstr;
275 } else {
276 err_msg = dp_err_to_string(req, dp_err_type, errnum);
277 }
278 if (!err_msg) {
279 DEBUG(1, ("Failed to set err_msg, Out of memory?\n"));
280 err_msg = "OOM";
281 }
282
283 dbret = dbus_message_append_args(reply,
284 DBUS_TYPE_UINT16, &err_maj,
285 DBUS_TYPE_UINT32, &err_min,
286 DBUS_TYPE_STRING, &err_msg,
287 DBUS_TYPE_INVALID);
288 if (!dbret) {
289 DEBUG(1, ("Failed to generate dbus reply\n"));
290 return;
291 }
292
293 dbus_conn = sbus_get_connection(req->becli->conn);
294 dbus_connection_send(dbus_conn, reply, NULL);
295 dbus_message_unref(reply);
296
297 DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
298 err_maj, err_min, err_msg));
299 }
300
301 /* finally free the request */
302 talloc_free(req);
303 }
304
305 static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn)
306 {
307 struct be_acct_req *req;
308 struct be_req *be_req;
309 struct be_client *becli;
310 DBusMessage *reply;
311 DBusError dbus_error;
312 dbus_bool_t dbret;
313 void *user_data;
314 uint32_t type;
315 char *filter;
316 int filter_type;
317 uint32_t attr_type;
318 char *filter_val;
319 int ret;
320 dbus_uint16_t err_maj;
321 dbus_uint32_t err_min;
322 const char *err_msg;
323
324 be_req = NULL;
325
326 user_data = sbus_conn_get_private_data(conn);
327 if (!user_data) return EINVAL;
328 becli = talloc_get_type(user_data, struct be_client);
329 if (!becli) return EINVAL;
330
331 dbus_error_init(&dbus_error);
332
333 ret = dbus_message_get_args(message, &dbus_error,
334 DBUS_TYPE_UINT32, &type,
335 DBUS_TYPE_UINT32, &attr_type,
336 DBUS_TYPE_STRING, &filter,
337 DBUS_TYPE_INVALID);
338 if (!ret) {
339 DEBUG(1,("Failed, to parse message!\n"));
340 if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
341 return EIO;
342 }
343
344 DEBUG(4, ("Got request for [%u][%d][%s]\n", type, attr_type, filter));
345
346 reply = dbus_message_new_method_return(message);
347 if (!reply) return ENOMEM;
348
349 /* If we are offline and fast reply was requested
350 * return offline immediately
351 */
352 if ((type & BE_REQ_FAST) && becli->bectx->offstat.offline) {
353 /* Send back an immediate reply */
354 err_maj = DP_ERR_OFFLINE;
355 err_min = EAGAIN;
356 err_msg = "Fast reply - offline";
357
358 dbret = dbus_message_append_args(reply,
359 DBUS_TYPE_UINT16, &err_maj,
360 DBUS_TYPE_UINT32, &err_min,
361 DBUS_TYPE_STRING, &err_msg,
362 DBUS_TYPE_INVALID);
363 if (!dbret) return EIO;
364
365 DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
366 err_maj, err_min, err_msg));
367
368 sbus_conn_send_reply(conn, reply);
369 dbus_message_unref(reply);
370 reply = NULL;
371 /* This reply will be queued and sent
372 * when we reenter the mainloop.
373 *
374 * Continue processing in case we are
375 * going back online.
376 */
377 }
378
379 if ((attr_type != BE_ATTR_CORE) &&
380 (attr_type != BE_ATTR_MEM) &&
381 (attr_type != BE_ATTR_ALL)) {
382 /* Unrecognized attr type */
383 err_maj = DP_ERR_FATAL;
384 err_min = EINVAL;
385 err_msg = "Invalid Attrs Parameter";
386 goto done;
387 }
388
389 if (filter) {
390 if (strncmp(filter, "name=", 5) == 0) {
391 filter_type = BE_FILTER_NAME;
392 filter_val = &filter[5];
393 } else if (strncmp(filter, "idnumber=", 9) == 0) {
394 filter_type = BE_FILTER_IDNUM;
395 filter_val = &filter[9];
396 } else {
397 err_maj = DP_ERR_FATAL;
398 err_min = EINVAL;
399 err_msg = "Invalid Filter";
400 goto done;
401 }
402 } else {
403 err_maj = DP_ERR_FATAL;
404 err_min = EINVAL;
405 err_msg = "Missing Filter Parameter";
406 goto done;
407 }
408
409 /* process request */
410 be_req = talloc_zero(becli, struct be_req);
411 if (!be_req) {
412 err_maj = DP_ERR_FATAL;
413 err_min = ENOMEM;
414 err_msg = "Out of memory";
415 goto done;
416 }
417 be_req->becli = becli;
418 be_req->be_ctx = becli->bectx;
419 be_req->fn = acctinfo_callback;
420 be_req->pvt = reply;
421
422 req = talloc(be_req, struct be_acct_req);
423 if (!req) {
424 err_maj = DP_ERR_FATAL;
425 err_min = ENOMEM;
426 err_msg = "Out of memory";
427 goto done;
428 }
429 req->entry_type = type;
430 req->attr_type = (int)attr_type;
431 req->filter_type = filter_type;
432 req->filter_value = talloc_strdup(req, filter_val);
433
434 be_req->req_data = req;
435
436 ret = be_file_request(becli->bectx,
437 becli->bectx->bet_info[BET_ID].bet_ops->handler,
438 be_req);
439 if (ret != EOK) {
440 err_maj = DP_ERR_FATAL;
441 err_min = ret;
442 err_msg = "Failed to file request";
443 goto done;
444 }
445
446 return EOK;
447
448 done:
449 if (be_req) {
450 talloc_free(be_req);
451 }
452
453 if (reply) {
454 dbret = dbus_message_append_args(reply,
455 DBUS_TYPE_UINT16, &err_maj,
456 DBUS_TYPE_UINT32, &err_min,
457 DBUS_TYPE_STRING, &err_msg,
458 DBUS_TYPE_INVALID);
459 if (!dbret) return EIO;
460
461 DEBUG(4, ("Request processed. Returned %d,%d,%s\n",
462 err_maj, err_min, err_msg));
463
464 /* send reply back */
465 sbus_conn_send_reply(conn, reply);
466 dbus_message_unref(reply);
467 }
468
469 return EOK;
470 }
471
472 static void be_pam_handler_callback(struct be_req *req,
473 int dp_err_type,
474 int errnum,
475 const char *errstr)
476 {
477 struct pam_data *pd;
478 DBusMessage *reply;
479 DBusConnection *dbus_conn;
480 dbus_bool_t dbret;
481
482 DEBUG(4, ("Backend returned: (%d, %d, %s) [%s]\n",
483 dp_err_type, errnum, errstr?errstr:"<NULL>",
484 dp_err_to_string(req, dp_err_type, errnum)));
485
486 pd = talloc_get_type(req->req_data, struct pam_data);
487
488 DEBUG(4, ("Sending result [%d][%s]\n", pd->pam_status, pd->domain));
489 reply = (DBusMessage *)req->pvt;
490 dbret = dp_pack_pam_response(reply, pd);
491 if (!dbret) {
492 DEBUG(1, ("Failed to generate dbus reply\n"));
493 dbus_message_unref(reply);
494 return;
495 }
496
497 dbus_conn = sbus_get_connection(req->becli->conn);
498 dbus_connection_send(dbus_conn, reply, NULL);
499 dbus_message_unref(reply);
500
501 DEBUG(4, ("Sent result [%d][%s]\n", pd->pam_status, pd->domain));
502
503 talloc_free(req);
504 }
505
506 static int be_pam_handler(DBusMessage *message, struct sbus_connection *conn)
507 {
508 DBusError dbus_error;
509 DBusMessage *reply;
510 struct be_client *becli;
511 dbus_bool_t ret;
512 void *user_data;
513 struct pam_data *pd = NULL;
514 struct be_req *be_req = NULL;
515 enum bet_type target = BET_NULL;
516
517 user_data = sbus_conn_get_private_data(conn);
At conditional (1): "!user_data": Taking false branch.
|
518 if (!user_data) return EINVAL;
519 becli = talloc_get_type(user_data, struct be_client);
At conditional (2): "!becli": Taking false branch.
|
520 if (!becli) return EINVAL;
521
522 reply = dbus_message_new_method_return(message);
At conditional (3): "!reply": Taking false branch.
|
523 if (!reply) {
524 DEBUG(1, ("dbus_message_new_method_return failed, cannot send reply.\n"));
525 return ENOMEM;
526 }
527
528 be_req = talloc_zero(becli, struct be_req);
At conditional (4): "!be_req": Taking true branch.
|
529 if (!be_req) {
At conditional (5): "7 <= debug_level": Taking true branch.
At conditional (6): "debug_timestamps": Taking true branch.
| |
530 DEBUG(7, ("talloc_zero failed.\n"));
531 goto done;
532 }
533
534 be_req->becli = becli;
535 be_req->be_ctx = becli->bectx;
536 be_req->fn = be_pam_handler_callback;
537 be_req->pvt = reply;
538
539 dbus_error_init(&dbus_error);
540
541 ret = dp_unpack_pam_request(message, be_req, &pd, &dbus_error);
542 if (!ret) {
543 DEBUG(1,("Failed, to parse message!\n"));
544 talloc_free(be_req);
545 return EIO;
546 }
547
548 pd->pam_status = PAM_SYSTEM_ERR;
549 pd->domain = talloc_strdup(pd, becli->bectx->domain->name);
550 if (pd->domain == NULL) {
551 talloc_free(be_req);
552 return ENOMEM;
553 }
554
555
556 DEBUG(4, ("Got request with the following data\n"));
557 DEBUG_PAM_DATA(4, pd);
558
559 switch (pd->cmd) {
560 case SSS_PAM_AUTHENTICATE:
561 target = BET_AUTH;
562 break;
563 case SSS_PAM_ACCT_MGMT:
564 target = BET_ACCESS;
565 break;
566 case SSS_PAM_CHAUTHTOK:
567 case SSS_PAM_CHAUTHTOK_PRELIM:
568 target = BET_CHPASS;
569 break;
570 case SSS_PAM_SETCRED:
571 case SSS_PAM_OPEN_SESSION:
572 case SSS_PAM_CLOSE_SESSION:
573 pd->pam_status = PAM_SUCCESS;
574 goto done;
575 break;
576 default:
577 DEBUG(7, ("Unsupported PAM command [%d].\n", pd->cmd));
578 pd->pam_status = PAM_MODULE_UNKNOWN;
579 goto done;
580 }
581
582 /* return an error if corresponding backend target is not configured */
583 if (!becli->bectx->bet_info[target].bet_ops) {
584 DEBUG(7, ("Undefined backend target.\n"));
585 pd->pam_status = PAM_MODULE_UNKNOWN;
586 ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO,
587 sizeof(MSG_TARGET_NO_CONFIGURED),
588 (const uint8_t *) MSG_TARGET_NO_CONFIGURED);
589 if (ret != EOK) {
590 DEBUG(1, ("pam_add_response failed.\n"));
591 }
592 goto done;
593 }
594
595 be_req->req_data = pd;
596
597 ret = be_file_request(becli->bectx,
598 becli->bectx->bet_info[target].bet_ops->handler,
599 be_req);
600 if (ret != EOK) {
601 DEBUG(7, ("be_file_request failed.\n"));
602 goto done;
603 }
604
605 return EOK;
606
607 done:
608
Event var_deref_op: Dereferencing null variable "pd".
Also see events: [assign_zero][var_deref_model]At conditional (7): "4 <= debug_level": Taking true branch.
At conditional (8): "debug_timestamps": Taking true branch.
| | | |
609 DEBUG(4, ("Sending result [%d][%s]\n",
610 pd->pam_status, pd->domain));
611
Event var_deref_model: Passing null variable "pd" to function "dp_pack_pam_response", which dereferences it. [model]
Also see events: [assign_zero][var_deref_op] | |
612 ret = dp_pack_pam_response(reply, pd);
613 if (!ret) {
614 DEBUG(1, ("Failed to generate dbus reply\n"));
615 talloc_free(be_req);
616 dbus_message_unref(reply);
617 return EIO;
618 }
619
620 /* send reply back immediately */
621 sbus_conn_send_reply(conn, reply);
622 dbus_message_unref(reply);
623
624 talloc_free(be_req);
625
626 return EOK;
627 }
628
629 static int be_client_destructor(void *ctx)
630 {
631 struct be_client *becli = talloc_get_type(ctx, struct be_client);
632 if (becli->bectx) {
633 if (becli->bectx->nss_cli == becli) {
634 DEBUG(4, ("Removed NSS client\n"));
635 becli->bectx->nss_cli = NULL;
636 } else if (becli->bectx->pam_cli == becli) {
637 DEBUG(4, ("Removed PAM client\n"));
638 becli->bectx->pam_cli = NULL;
639 } else {
640 DEBUG(2, ("Unknown client removed ...\n"));
641 }
642 }
643 return 0;
644 }
645
646 static int client_registration(DBusMessage *message,
647 struct sbus_connection *conn)
648 {
649 dbus_uint16_t version = DATA_PROVIDER_VERSION;
650 struct be_client *becli;
651 DBusMessage *reply;
652 DBusError dbus_error;
653 dbus_uint16_t cli_ver;
654 char *cli_name;
655 dbus_bool_t dbret;
656 void *data;
657
658 data = sbus_conn_get_private_data(conn);
659 becli = talloc_get_type(data, struct be_client);
660 if (!becli) {
661 DEBUG(0, ("Connection holds no valid init data\n"));
662 return EINVAL;
663 }
664
665 /* First thing, cancel the timeout */
666 DEBUG(4, ("Cancel DP ID timeout [%p]\n", becli->timeout));
667 talloc_zfree(becli->timeout);
668
669 dbus_error_init(&dbus_error);
670
671 dbret = dbus_message_get_args(message, &dbus_error,
672 DBUS_TYPE_UINT16, &cli_ver,
673 DBUS_TYPE_STRING, &cli_name,
674 DBUS_TYPE_INVALID);
675 if (!dbret) {
676 DEBUG(1, ("Failed to parse message, killing connection\n"));
677 if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
678 sbus_disconnect(conn);
679 /* FIXME: should we just talloc_zfree(conn) ? */
680 return EIO;
681 }
682
683 if (strcasecmp(cli_name, "NSS") == 0) {
684 becli->bectx->nss_cli = becli;
685 } else if (strcasecmp(cli_name, "PAM") == 0) {
686 becli->bectx->pam_cli = becli;
687 } else {
688 DEBUG(1, ("Unknown client! [%s]\n", cli_name));
689 }
690 talloc_set_destructor((TALLOC_CTX *)becli, be_client_destructor);
691
692 DEBUG(4, ("Added Frontend client [%s]\n", cli_name));
693
694 /* reply that all is ok */
695 reply = dbus_message_new_method_return(message);
696 if (!reply) {
697 DEBUG(0, ("Dbus Out of memory!\n"));
698 return ENOMEM;
699 }
700
701 dbret = dbus_message_append_args(reply,
702 DBUS_TYPE_UINT16, &version,
703 DBUS_TYPE_INVALID);
704 if (!dbret) {
705 DEBUG(0, ("Failed to build dbus reply\n"));
706 dbus_message_unref(reply);
707 sbus_disconnect(conn);
708 return EIO;
709 }
710
711 /* send reply back */
712 sbus_conn_send_reply(conn, reply);
713 dbus_message_unref(reply);
714
715 becli->initialized = true;
716 return EOK;
717 }
718
719 static void init_timeout(struct tevent_context *ev,
720 struct tevent_timer *te,
721 struct timeval t, void *ptr)
722 {
723 struct be_client *becli;
724
725 DEBUG(2, ("Client timed out before Identification [%p]!\n", te));
726
727 becli = talloc_get_type(ptr, struct be_client);
728
729 sbus_disconnect(becli->conn);
730 talloc_zfree(becli);
731 }
732
733 static int be_client_init(struct sbus_connection *conn, void *data)
734 {
735 struct be_ctx *bectx;
736 struct be_client *becli;
737 struct timeval tv;
738
739 bectx = talloc_get_type(data, struct be_ctx);
740
741 /* hang off this memory to the connection so that when the connection
742 * is freed we can potentially call a destructor */
743
744 becli = talloc(conn, struct be_client);
745 if (!becli) {
746 DEBUG(0,("Out of memory?!\n"));
747 talloc_zfree(conn);
748 return ENOMEM;
749 }
750 becli->bectx = bectx;
751 becli->conn = conn;
752 becli->initialized = false;
753
754 /* 5 seconds should be plenty */
755 tv = tevent_timeval_current_ofs(5, 0);
756
757 becli->timeout = tevent_add_timer(bectx->ev, becli,
758 tv, init_timeout, becli);
759 if (!becli->timeout) {
760 DEBUG(0,("Out of memory?!\n"));
761 talloc_zfree(conn);
762 return ENOMEM;
763 }
764 DEBUG(4, ("Set-up Backend ID timeout [%p]\n", becli->timeout));
765
766 /* Attach the client context to the connection context, so that it is
767 * always available when we need to manage the connection. */
768 sbus_conn_set_private_data(conn, becli);
769
770 return EOK;
771 }
772
773 /* be_srv_init
774 * set up per-domain sbus channel */
775 static int be_srv_init(struct be_ctx *ctx)
776 {
777 char *sbus_address;
778 int ret;
779
780 /* Set up SBUS connection to the monitor */
781 ret = dp_get_sbus_address(ctx, &sbus_address, ctx->domain->name);
782 if (ret != EOK) {
783 DEBUG(0, ("Could not get sbus backend address.\n"));
784 return ret;
785 }
786
787 ret = sbus_new_server(ctx, ctx->ev, sbus_address,
788 &be_interface, &ctx->sbus_srv,
789 be_client_init, ctx);
790 if (ret != EOK) {
791 DEBUG(0, ("Could not set up sbus server.\n"));
792 return ret;
793 }
794
795 return EOK;
796 }
797
798 /* mon_cli_init
799 * sbus channel to the monitor daemon */
800 static int mon_cli_init(struct be_ctx *ctx)
801 {
802 char *sbus_address;
803 int ret;
804
805 /* Set up SBUS connection to the monitor */
806 ret = monitor_get_sbus_address(ctx, &sbus_address);
807 if (ret != EOK) {
808 DEBUG(0, ("Could not locate monitor address.\n"));
809 return ret;
810 }
811
812 ret = sbus_client_init(ctx, ctx->ev, sbus_address,
813 &monitor_be_interface, &ctx->mon_conn,
814 NULL, ctx);
815 if (ret != EOK) {
816 DEBUG(0, ("Failed to connect to monitor services.\n"));
817 return ret;
818 }
819
820 /* Identify ourselves to the monitor */
821 ret = monitor_common_send_id(ctx->mon_conn,
822 ctx->identity,
823 DATA_PROVIDER_VERSION);
824 if (ret != EOK) {
825 DEBUG(0, ("Failed to identify to the monitor!\n"));
826 return ret;
827 }
828
829 return EOK;
830 }
831
832 static void be_target_access_permit(struct be_req *be_req)
833 {
834 struct pam_data *pd = talloc_get_type(be_req->req_data, struct pam_data);
835 DEBUG(9, ("be_target_access_permit called, returning PAM_SUCCESS.\n"));
836
837 pd->pam_status = PAM_SUCCESS;
838 be_req->fn(be_req, DP_ERR_OK, PAM_SUCCESS, NULL);
839 }
840
841 static struct bet_ops be_target_access_permit_ops = {
842 .check_online = NULL,
843 .handler = be_target_access_permit,
844 .finalize = NULL
845 };
846
847 static void be_target_access_deny(struct be_req *be_req)
848 {
849 struct pam_data *pd = talloc_get_type(be_req->req_data, struct pam_data);
850 DEBUG(9, ("be_target_access_deny called, returning PAM_PERM_DENIED.\n"));
851
852 pd->pam_status = PAM_PERM_DENIED;
853 be_req->fn(be_req, DP_ERR_OK, PAM_PERM_DENIED, NULL);
854 }
855
856 static struct bet_ops be_target_access_deny_ops = {
857 .check_online = NULL,
858 .handler = be_target_access_deny,
859 .finalize = NULL
860 };
861
862 static int load_backend_module(struct be_ctx *ctx,
863 enum bet_type bet_type,
864 struct bet_info *bet_info,
865 const char *default_mod_name)
866 {
867 TALLOC_CTX *tmp_ctx;
868 int ret = EINVAL;
869 bool already_loaded = false;
870 int lb=0;
871 char *mod_name = NULL;
872 char *path = NULL;
873 void *handle;
874 char *mod_init_fn_name = NULL;
875 bet_init_fn_t mod_init_fn = NULL;
876
877 (*bet_info).mod_name = NULL;
878 (*bet_info).bet_ops = NULL;
879 (*bet_info).pvt_bet_data = NULL;
880
881 if (bet_type <= BET_NULL || bet_type >= BET_MAX ||
882 bet_type != bet_data[bet_type].bet_type) {
883 DEBUG(2, ("invalid bet_type or bet_data corrupted.\n"));
884 return EINVAL;
885 }
886
887 tmp_ctx = talloc_new(ctx);
888 if (!tmp_ctx) {
889 DEBUG(7, ("talloc_new failed.\n"));
890 return ENOMEM;
891 }
892
893 ret = confdb_get_string(ctx->cdb, tmp_ctx, ctx->conf_path,
894 bet_data[bet_type].option_name, NULL,
895 &mod_name);
896 if (ret != EOK) {
897 ret = EFAULT;
898 goto done;
899 }
900 if (!mod_name) {
901 if (default_mod_name != NULL) {
902 DEBUG(5, ("no module name found in confdb, using [%s].\n",
903 default_mod_name));
904 mod_name = talloc_strdup(ctx, default_mod_name);
905 } else {
906 ret = ENOENT;
907 goto done;
908 }
909 }
910
911 if (strcasecmp(mod_name, NO_PROVIDER) == 0) {
912 ret = ENOENT;
913 goto done;
914 }
915
916 if (bet_type == BET_ACCESS) {
917 if (strcmp(mod_name, ACCESS_PERMIT) == 0) {
918 (*bet_info).bet_ops = &be_target_access_permit_ops;
919 (*bet_info).pvt_bet_data = NULL;
920 (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_PERMIT);
921
922 ret = EOK;
923 goto done;
924 }
925 if (strcmp(mod_name, ACCESS_DENY) == 0) {
926 (*bet_info).bet_ops = &be_target_access_deny_ops;
927 (*bet_info).pvt_bet_data = NULL;
928 (*bet_info).mod_name = talloc_strdup(ctx, ACCESS_DENY);
929
930 ret = EOK;
931 goto done;
932 }
933 }
934
935 mod_init_fn_name = talloc_asprintf(tmp_ctx,
936 bet_data[bet_type].mod_init_fn_name_fmt,
937 mod_name);
938 if (mod_init_fn_name == NULL) {
939 DEBUG(7, ("talloc_asprintf failed\n"));
940 ret = ENOMEM;
941 goto done;
942 }
943
944
945 lb = 0;
946 while(ctx->loaded_be[lb].be_name != NULL) {
947 if (strncmp(ctx->loaded_be[lb].be_name, mod_name,
948 strlen(mod_name)) == 0) {
949 DEBUG(7, ("Backend [%s] already loaded.\n", mod_name));
950 already_loaded = true;
951 break;
952 }
953
954 ++lb;
955 if (lb >= BET_MAX) {
956 DEBUG(2, ("Backend context corrupted.\n"));
957 ret = EINVAL;
958 goto done;
959 }
960 }
961
962 if (!already_loaded) {
963 path = talloc_asprintf(tmp_ctx, "%s/libsss_%s.so",
964 DATA_PROVIDER_PLUGINS_PATH, mod_name);
965 if (!path) {
966 ret = ENOMEM;
967 goto done;
968 }
969
970 DEBUG(7, ("Loading backend [%s] with path [%s].\n", mod_name, path));
971 handle = dlopen(path, RTLD_NOW);
972 if (!handle) {
973 DEBUG(0, ("Unable to load %s module with path (%s), error: %s\n",
974 mod_name, path, dlerror()));
975 ret = ELIBACC;
976 goto done;
977 }
978
979 ctx->loaded_be[lb].be_name = talloc_strdup(ctx, mod_name);
980 ctx->loaded_be[lb].handle = handle;
981 }
982
983 mod_init_fn = (bet_init_fn_t)dlsym(ctx->loaded_be[lb].handle,
984 mod_init_fn_name);
985 if (mod_init_fn == NULL) {
986 if (default_mod_name != NULL &&
987 strcmp(default_mod_name, mod_name) == 0 ) {
988 /* If the default is used and fails we indicate this to the caller
989 * by returning ENOENT. Ths way the caller can decide how to
990 * handle the different types of error conditions. */
991 ret = ENOENT;
992 } else {
993 DEBUG(0, ("Unable to load init fn %s from module %s, error: %s\n",
994 mod_init_fn_name, mod_name, dlerror()));
995 ret = ELIBBAD;
996 }
997 goto done;
998 }
999
1000 ret = mod_init_fn(ctx, &(*bet_info).bet_ops, &(*bet_info).pvt_bet_data);
1001 if (ret != EOK) {
1002 DEBUG(0, ("Error (%d) in module (%s) initialization (%s)!\n",
1003 ret, mod_name, mod_init_fn_name));
1004 goto done;
1005 }
1006
1007 (*bet_info).mod_name = talloc_strdup(ctx, mod_name);
1008
1009 ret = EOK;
1010
1011 done:
1012 talloc_free(tmp_ctx);
1013 return ret;
1014 }
1015
1016 static void signal_be_offline(struct tevent_context *ev,
1017 struct tevent_signal *se,
1018 int signum,
1019 int count,
1020 void *siginfo,
1021 void *private_data)
1022 {
1023 struct be_ctx *ctx = talloc_get_type(private_data, struct be_ctx);
1024 be_mark_offline(ctx);
1025 }
1026
1027 int be_process_init(TALLOC_CTX *mem_ctx,
1028 const char *be_domain,
1029 struct tevent_context *ev,
1030 struct confdb_ctx *cdb)
1031 {
1032 struct be_ctx *ctx;
1033 struct tevent_signal *tes;
1034 int ret;
1035
1036 ctx = talloc_zero(mem_ctx, struct be_ctx);
1037 if (!ctx) {
1038 DEBUG(0, ("fatal error initializing be_ctx\n"));
1039 return ENOMEM;
1040 }
1041 ctx->ev = ev;
1042 ctx->cdb = cdb;
1043 ctx->identity = talloc_asprintf(ctx, "%%BE_%s", be_domain);
1044 ctx->conf_path = talloc_asprintf(ctx, CONFDB_DOMAIN_PATH_TMPL, be_domain);
1045 if (!ctx->identity || !ctx->conf_path) {
1046 DEBUG(0, ("Out of memory!?\n"));
1047 return ENOMEM;
1048 }
1049
1050 ret = be_init_failover(ctx);
1051 if (ret != EOK) {
1052 DEBUG(0, ("fatal error initializing failover context\n"));
1053 return ret;
1054 }
1055
1056 ret = confdb_get_domain(cdb, be_domain, &ctx->domain);
1057 if (ret != EOK) {
1058 DEBUG(0, ("fatal error retrieving domain configuration\n"));
1059 return ret;
1060 }
1061
1062 ret = sysdb_domain_init(ctx, ev, ctx->domain, DB_PATH, &ctx->sysdb);
1063 if (ret != EOK) {
1064 DEBUG(0, ("fatal error opening cache database\n"));
1065 return ret;
1066 }
1067
1068 ret = mon_cli_init(ctx);
1069 if (ret != EOK) {
1070 DEBUG(0, ("fatal error setting up monitor bus\n"));
1071 return ret;
1072 }
1073
1074 ret = be_srv_init(ctx);
1075 if (ret != EOK) {
1076 DEBUG(0, ("fatal error setting up server bus\n"));
1077 return ret;
1078 }
1079
1080 ret = load_backend_module(ctx, BET_ID,
1081 &ctx->bet_info[BET_ID], NULL);
1082 if (ret != EOK) {
1083 DEBUG(0, ("fatal error initializing data providers\n"));
1084 return ret;
1085 }
1086 DEBUG(9, ("ID backend target successfully loaded from provider [%s].\n",
1087 ctx->bet_info[BET_ID].mod_name));
1088
1089 ret = load_backend_module(ctx, BET_AUTH,
1090 &ctx->bet_info[BET_AUTH],
1091 ctx->bet_info[BET_ID].mod_name);
1092 if (ret != EOK) {
1093 if (ret != ENOENT) {
1094 DEBUG(0, ("fatal error initializing data providers\n"));
1095 return ret;
1096 }
1097 DEBUG(1, ("No authentication module provided for [%s] !!\n",
1098 be_domain));
1099 } else {
1100 DEBUG(9, ("AUTH backend target successfully loaded "
1101 "from provider [%s].\n", ctx->bet_info[BET_AUTH].mod_name));
1102 }
1103
1104 ret = load_backend_module(ctx, BET_ACCESS, &ctx->bet_info[BET_ACCESS],
1105 ACCESS_PERMIT);
1106 if (ret != EOK) {
1107 DEBUG(0, ("Failed to setup ACCESS backend.\n"));
1108 return ret;
1109 }
1110 DEBUG(9, ("ACCESS backend target successfully loaded "
1111 "from provider [%s].\n", ctx->bet_info[BET_ACCESS].mod_name));
1112
1113 ret = load_backend_module(ctx, BET_CHPASS,
1114 &ctx->bet_info[BET_CHPASS],
1115 ctx->bet_info[BET_AUTH].mod_name);
1116 if (ret != EOK) {
1117 if (ret != ENOENT) {
1118 DEBUG(0, ("fatal error initializing data providers\n"));
1119 return ret;
1120 }
1121 DEBUG(1, ("No change password module provided for [%s] !!\n",
1122 be_domain));
1123 } else {
1124 DEBUG(9, ("CHPASS backend target successfully loaded "
1125 "from provider [%s].\n", ctx->bet_info[BET_CHPASS].mod_name));
1126 }
1127
1128 /* Handle SIGUSR1 to force offline behavior */
1129 BlockSignals(false, SIGUSR1);
1130 tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
1131 signal_be_offline, ctx);
1132 if (tes == NULL) {
1133 return EIO;
1134 }
1135
1136 return EOK;
1137 }
1138
1139 int main(int argc, const char *argv[])
1140 {
1141 int opt;
1142 poptContext pc;
1143 char *be_domain = NULL;
1144 char *srv_name = NULL;
1145 char *conf_entry = NULL;
1146 struct main_context *main_ctx;
1147 int ret;
1148
1149 struct poptOption long_options[] = {
1150 POPT_AUTOHELP
1151 SSSD_MAIN_OPTS
1152 {"domain", 0, POPT_ARG_STRING, &be_domain, 0,
1153 _("Domain of the information provider (mandatory)"), NULL },
1154 POPT_TABLEEND
1155 };
1156
1157 pc = poptGetContext(argv[0], argc, argv, long_options, 0);
1158 while((opt = poptGetNextOpt(pc)) != -1) {
1159 switch(opt) {
1160 default:
1161 fprintf(stderr, "\nInvalid option %s: %s\n\n",
1162 poptBadOption(pc, 0), poptStrerror(opt));
1163 poptPrintUsage(pc, stderr, 0);
1164 return 1;
1165 }
1166 }
1167
1168 if (be_domain == NULL) {
1169 fprintf(stderr, "\nMissing option, --domain is a mandatory option.\n\n");
1170 poptPrintUsage(pc, stderr, 0);
1171 return 1;
1172 }
1173
1174 poptFreeContext(pc);
1175
1176
1177 /* set up things like debug , signals, daemonization, etc... */
1178 debug_log_file = talloc_asprintf(NULL, "sssd_%s", be_domain);
1179 if (!debug_log_file) return 2;
1180
1181 srv_name = talloc_asprintf(NULL, "sssd[be[%s]]", be_domain);
1182 if (!srv_name) return 2;
1183
1184 conf_entry = talloc_asprintf(NULL, CONFDB_DOMAIN_PATH_TMPL, be_domain);
1185 if (!conf_entry) return 2;
1186
1187 ret = server_setup(srv_name, 0, conf_entry, &main_ctx);
1188 if (ret != EOK) {
1189 DEBUG(0, ("Could not set up mainloop [%d]\n", ret));
1190 return 2;
1191 }
1192
1193 ret = die_if_parent_died();
1194 if (ret != EOK) {
1195 /* This is not fatal, don't return */
1196 DEBUG(2, ("Could not set up to exit when parent process does\n"));
1197 }
1198
1199 ret = be_process_init(main_ctx,
1200 be_domain,
1201 main_ctx->event_ctx,
1202 main_ctx->confdb_ctx);
1203 if (ret != EOK) {
1204 DEBUG(0, ("Could not initialize backend [%d]\n", ret));
1205 return 3;
1206 }
1207
1208 DEBUG(1, ("Backend provider (%s) started!\n", be_domain));
1209
1210 /* loop on main */
1211 server_loop(main_ctx);
1212
1213 return 0;
1214 }
1215
1216 static int data_provider_res_init(DBusMessage *message,
1217 struct sbus_connection *conn)
1218 {
1219 resolv_reread_configuration();
1220
1221 return monitor_common_res_init(message, conn);
1222 }
1223
1224 static int data_provider_go_offline(DBusMessage *message,
1225 struct sbus_connection *conn)
1226 {
1227 struct be_ctx *be_ctx;
1228 be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx);
1229 be_mark_offline(be_ctx);
1230 return monitor_common_pong(message, conn);
1231 }