Line data Source code
1 : /*
2 : SSSD
3 :
4 : Service monitor
5 :
6 : Copyright (C) Simo Sorce 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 "util/util.h"
23 : #include "util/child_common.h"
24 : #include <sys/types.h>
25 : #include <sys/wait.h>
26 : #include <sys/time.h>
27 : #include <sys/param.h>
28 : #include <time.h>
29 : #include <string.h>
30 : #ifdef HAVE_SYS_INOTIFY_H
31 : #include <sys/inotify.h>
32 : #endif
33 : #include <sys/types.h>
34 : #include <sys/stat.h>
35 : #include <unistd.h>
36 : #include <fcntl.h>
37 : #include <popt.h>
38 : #include <tevent.h>
39 : #include <dbus/dbus.h>
40 :
41 : /* Needed for res_init() */
42 : #include <netinet/in.h>
43 : #include <arpa/nameser.h>
44 : #include <resolv.h>
45 :
46 : #include "confdb/confdb.h"
47 : #include "confdb/confdb_setup.h"
48 : #include "db/sysdb.h"
49 : #include "monitor/monitor.h"
50 : #include "sbus/sssd_dbus.h"
51 : #include "monitor/monitor_interfaces.h"
52 : #include "responder/common/responder_sbus.h"
53 :
54 : #ifdef USE_KEYRING
55 : #include <keyutils.h>
56 : #endif
57 :
58 : /* ping time cannot be less then once every few seconds or the
59 : * monitor will get crazy hammering children with messages */
60 : #define MONITOR_DEF_PING_TIME 10
61 : /* terminate the child after this interval by default if it
62 : * doesn't shutdown on receiving SIGTERM */
63 : #define MONITOR_DEF_FORCE_TIME 60
64 :
65 : /* TODO: get the restart related values from config */
66 : #define MONITOR_RESTART_CNT_INTERVAL_RESET 30
67 : /* maximum allowed number of service restarts if the restarts
68 : * were less than MONITOR_RESTART_CNT_INTERVAL_RESET apart, which would
69 : * indicate a crash after startup or after every request */
70 : #define MONITOR_MAX_SVC_RESTARTS 2
71 : /* The services are restarted with a delay in case the restart was
72 : * hitting a race condition where the DP is not ready yet either.
73 : * The MONITOR_MAX_RESTART_DELAY defines the maximum delay between
74 : * restarts.
75 : */
76 : #define MONITOR_MAX_RESTART_DELAY 4
77 :
78 : /* name of the monitor server instance */
79 : #define MONITOR_NAME "sssd"
80 : #define SSSD_PIDFILE_PATH PID_PATH"/"MONITOR_NAME".pid"
81 :
82 : /* Special value to leave the Kerberos Replay Cache set to use
83 : * the libkrb5 defaults
84 : */
85 : #define KRB5_RCACHE_DIR_DISABLE "__LIBKRB5_DEFAULTS__"
86 :
87 : /* Warning messages */
88 : #define CONF_FILE_PERM_ERROR_MSG "Cannot read config file %s. Please check "\
89 : "that the file is accessible only by the "\
90 : "owner and owned by root.root.\n"
91 :
92 : int cmdline_debug_level;
93 : int cmdline_debug_timestamps;
94 : int cmdline_debug_microseconds;
95 :
96 : struct svc_spy;
97 :
98 : enum mt_svc_type {
99 : MT_SVC_SERVICE,
100 : MT_SVC_PROVIDER
101 : };
102 :
103 : struct mt_svc {
104 : struct mt_svc *prev;
105 : struct mt_svc *next;
106 : enum mt_svc_type type;
107 :
108 : struct sbus_connection *conn;
109 : struct svc_spy *conn_spy;
110 :
111 : struct mt_ctx *mt_ctx;
112 :
113 : char *provider;
114 : char *command;
115 : char *name;
116 : char *identity;
117 : pid_t pid;
118 :
119 : int ping_time;
120 : int kill_time;
121 :
122 : struct tevent_timer *kill_timer;
123 :
124 : bool svc_started;
125 :
126 : int restarts;
127 : time_t last_restart;
128 : int failed_pongs;
129 : DBusPendingCall *pending;
130 :
131 : int debug_level;
132 :
133 : struct tevent_timer *ping_ev;
134 :
135 : struct sss_child_ctx *child_ctx;
136 : };
137 :
138 : struct config_file_callback {
139 : int wd;
140 : int retries;
141 : monitor_reconf_fn fn;
142 : char *filename;
143 : time_t modified;
144 : struct config_file_callback *next;
145 : struct config_file_callback *prev;
146 : };
147 :
148 : struct config_file_ctx {
149 : TALLOC_CTX *parent_ctx;
150 : struct tevent_timer *timer;
151 : bool needs_update;
152 : struct mt_ctx *mt_ctx;
153 : struct config_file_callback *callbacks;
154 : };
155 :
156 : struct mt_ctx {
157 : struct tevent_context *ev;
158 : struct confdb_ctx *cdb;
159 : struct sss_domain_info *domains;
160 : char **services;
161 : int num_services;
162 : int started_services;
163 : struct mt_svc *svc_list;
164 : struct sbus_connection *sbus_srv;
165 : struct config_file_ctx *file_ctx;
166 : int inotify_fd;
167 : int service_id_timeout;
168 : bool check_children;
169 : bool services_started;
170 : struct netlink_ctx *nlctx;
171 : const char *conf_path;
172 : struct sss_sigchild_ctx *sigchld_ctx;
173 : bool is_daemon;
174 : pid_t parent_pid;
175 :
176 : /* For running unprivileged services */
177 : uid_t uid;
178 : gid_t gid;
179 : };
180 :
181 : static int start_service(struct mt_svc *mt_svc);
182 :
183 : static int monitor_service_init(struct sbus_connection *conn, void *data);
184 :
185 : static int service_send_ping(struct mt_svc *svc);
186 : static int service_signal_reset_offline(struct mt_svc *svc);
187 : static void ping_check(DBusPendingCall *pending, void *data);
188 :
189 : static void set_tasks_checker(struct mt_svc *srv);
190 : static int monitor_kill_service (struct mt_svc *svc);
191 :
192 : static int get_service_config(struct mt_ctx *ctx, const char *name,
193 : struct mt_svc **svc_cfg);
194 : static int get_provider_config(struct mt_ctx *ctx, const char *name,
195 : struct mt_svc **svc_cfg);
196 : static int add_new_service(struct mt_ctx *ctx,
197 : const char *name,
198 : int restarts);
199 : static int add_new_provider(struct mt_ctx *ctx,
200 : const char *name,
201 : int restarts);
202 :
203 : static int mark_service_as_started(struct mt_svc *svc);
204 :
205 : static int monitor_cleanup(void);
206 :
207 0 : static void network_status_change_cb(void *cb_data)
208 : {
209 : struct mt_svc *iter;
210 0 : struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
211 :
212 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "A networking status change detected "
213 : "signaling providers to reset offline status\n");
214 0 : for (iter = ctx->svc_list; iter; iter = iter->next) {
215 : /* Don't signal services, only providers */
216 0 : if (iter->provider) {
217 0 : service_signal_reset_offline(iter);
218 : }
219 : }
220 0 : }
221 :
222 : /* dbus_get_monitor_version
223 : * Return the monitor version over D-BUS */
224 0 : static int get_monitor_version(struct sbus_request *dbus_req, void *data)
225 : {
226 0 : dbus_uint16_t version = MONITOR_VERSION;
227 :
228 0 : return sbus_request_return_and_finish(dbus_req,
229 : DBUS_TYPE_UINT16, &version,
230 : DBUS_TYPE_INVALID);
231 : }
232 :
233 : struct mon_init_conn {
234 : struct mt_ctx *ctx;
235 : struct sbus_connection *conn;
236 : struct tevent_timer *timeout;
237 : };
238 :
239 : static int add_svc_conn_spy(struct mt_svc *svc);
240 :
241 : /* registers a new client.
242 : * if operation is successful also sends back the Monitor version */
243 0 : static int client_registration(struct sbus_request *dbus_req, void *data)
244 : {
245 0 : dbus_uint16_t version = MONITOR_VERSION;
246 : struct mon_init_conn *mini;
247 : struct mt_svc *svc;
248 : DBusError dbus_error;
249 : dbus_uint16_t svc_ver;
250 : char *svc_name;
251 : dbus_bool_t dbret;
252 : int ret;
253 :
254 0 : mini = talloc_get_type(data, struct mon_init_conn);
255 0 : if (!mini) {
256 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Connection holds no valid init data\n");
257 0 : return EINVAL;
258 : }
259 :
260 : /* First thing, cancel the timeout */
261 0 : talloc_zfree(mini->timeout);
262 :
263 0 : dbus_error_init(&dbus_error);
264 :
265 0 : dbret = dbus_message_get_args(dbus_req->message, &dbus_error,
266 : DBUS_TYPE_STRING, &svc_name,
267 : DBUS_TYPE_UINT16, &svc_ver,
268 : DBUS_TYPE_INVALID);
269 0 : if (!dbret) {
270 0 : DEBUG(SSSDBG_CRIT_FAILURE,
271 : "Failed to parse message, killing connection\n");
272 0 : if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
273 0 : sbus_disconnect(dbus_req->conn);
274 0 : sbus_request_finish(dbus_req, NULL);
275 : /* FIXME: should we just talloc_zfree(conn) ? */
276 0 : goto done;
277 : }
278 :
279 0 : DEBUG(SSSDBG_CONF_SETTINGS,
280 : "Received ID registration: (%s,%d)\n", svc_name, svc_ver);
281 :
282 : /* search this service in the list */
283 0 : svc = mini->ctx->svc_list;
284 0 : while (svc) {
285 0 : ret = strcasecmp(svc->identity, svc_name);
286 0 : if (ret == 0) {
287 0 : break;
288 : }
289 0 : svc = svc->next;
290 : }
291 0 : if (!svc) {
292 0 : DEBUG(SSSDBG_FATAL_FAILURE,
293 : "Unable to find peer [%s] in list of services,"
294 : " killing connection!\n", svc_name);
295 0 : sbus_disconnect(dbus_req->conn);
296 0 : sbus_request_finish(dbus_req, NULL);
297 : /* FIXME: should we just talloc_zfree(conn) ? */
298 0 : goto done;
299 : }
300 :
301 : /* Fill in svc structure with connection data */
302 0 : svc->conn = mini->conn;
303 :
304 0 : ret = mark_service_as_started(svc);
305 0 : if (ret) {
306 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to mark service [%s]!\n", svc_name);
307 0 : goto done;
308 : }
309 :
310 : /* reply that all is ok */
311 0 : sbus_request_return_and_finish(dbus_req,
312 : DBUS_TYPE_UINT16, &version,
313 : DBUS_TYPE_INVALID);
314 :
315 : done:
316 : /* init complete, get rid of temp init context */
317 0 : talloc_zfree(mini);
318 :
319 0 : return EOK;
320 : }
321 :
322 : struct svc_spy {
323 : struct mt_svc *svc;
324 : };
325 :
326 0 : static int svc_destructor(void *mem)
327 : {
328 0 : struct mt_svc *svc = talloc_get_type(mem, struct mt_svc);
329 0 : if (!svc) {
330 : /* ?!?!? */
331 0 : return 0;
332 : }
333 :
334 : /* try to delist service */
335 0 : if (svc->mt_ctx) {
336 0 : DLIST_REMOVE(svc->mt_ctx->svc_list, svc);
337 : }
338 :
339 : /* Cancel any pending pings */
340 0 : if (svc->pending) {
341 0 : dbus_pending_call_cancel(svc->pending);
342 : }
343 :
344 : /* svc is being freed, neutralize the spy */
345 0 : if (svc->conn_spy) {
346 0 : talloc_set_destructor((TALLOC_CTX *)svc->conn_spy, NULL);
347 0 : talloc_zfree(svc->conn_spy);
348 : }
349 :
350 0 : if (svc->type == MT_SVC_SERVICE && svc->svc_started
351 0 : && svc->mt_ctx != NULL && svc->mt_ctx->started_services > 0) {
352 0 : svc->mt_ctx->started_services--;
353 : }
354 :
355 0 : return 0;
356 : }
357 :
358 0 : static int svc_spy_destructor(void *mem)
359 : {
360 0 : struct svc_spy *spy = talloc_get_type(mem, struct svc_spy);
361 0 : if (!spy) {
362 : /* ?!?!? */
363 0 : return 0;
364 : }
365 :
366 : /* svc->conn has been freed, NULL the pointer in svc */
367 0 : spy->svc->conn_spy = NULL;
368 0 : spy->svc->conn = NULL;
369 0 : return 0;
370 : }
371 :
372 0 : static int add_svc_conn_spy(struct mt_svc *svc)
373 : {
374 : struct svc_spy *spy;
375 :
376 0 : spy = talloc(svc->conn, struct svc_spy);
377 0 : if (!spy) return ENOMEM;
378 :
379 0 : spy->svc = svc;
380 0 : talloc_set_destructor((TALLOC_CTX *)spy, svc_spy_destructor);
381 0 : svc->conn_spy = spy;
382 :
383 0 : return EOK;
384 : }
385 :
386 0 : static int mark_service_as_started(struct mt_svc *svc)
387 : {
388 0 : struct mt_ctx *ctx = svc->mt_ctx;
389 : struct mt_svc *iter;
390 : int ret;
391 : int i;
392 :
393 0 : DEBUG(SSSDBG_FUNC_DATA, "Marking %s as started.\n", svc->name);
394 0 : svc->svc_started = true;
395 :
396 : /* we need to attach a spy to the connection structure so that if some code
397 : * frees it we can zero it out in the service structure. Otherwise we may
398 : * try to access or even free, freed memory. */
399 0 : ret = add_svc_conn_spy(svc);
400 0 : if (ret) {
401 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to attch spy\n");
402 0 : goto done;
403 : }
404 :
405 0 : if (!ctx->services_started) {
406 :
407 : /* check if all providers are up */
408 0 : for (iter = ctx->svc_list; iter; iter = iter->next) {
409 0 : if (iter->provider && !iter->svc_started) {
410 0 : DEBUG(SSSDBG_FUNC_DATA,
411 : "Still waiting on %s provider.\n", iter->name);
412 0 : break;
413 : }
414 : }
415 :
416 0 : if (iter) {
417 : /* there are still unstarted providers */
418 0 : goto done;
419 : }
420 :
421 0 : ctx->services_started = true;
422 :
423 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Now starting services!\n");
424 : /* then start all services */
425 0 : for (i = 0; ctx->services[i]; i++) {
426 0 : add_new_service(ctx, ctx->services[i], 0);
427 : }
428 : }
429 :
430 0 : if (svc->type == MT_SVC_SERVICE) {
431 0 : ctx->started_services++;
432 : }
433 :
434 0 : if (ctx->started_services == ctx->num_services) {
435 : /* Initialization is complete, terminate parent process if in daemon
436 : * mode. Make sure we send the signal to the right process */
437 0 : if (ctx->is_daemon) {
438 0 : if (ctx->parent_pid <= 1 || ctx->parent_pid != getppid()) {
439 : /* the parent process was already terminated */
440 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Invalid parent pid: %d\n",
441 : ctx->parent_pid);
442 0 : goto done;
443 : }
444 :
445 0 : DEBUG(SSSDBG_TRACE_FUNC, "SSSD is initialized, "
446 : "terminating parent process\n");
447 :
448 0 : errno = 0;
449 0 : ret = kill(ctx->parent_pid, SIGTERM);
450 0 : if (ret != 0) {
451 0 : ret = errno;
452 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Unable to terminate parent "
453 : "process [%d]: %s\n", ret, strerror(ret));
454 : }
455 : }
456 : }
457 :
458 : done:
459 0 : return ret;
460 : }
461 :
462 0 : static void services_startup_timeout(struct tevent_context *ev,
463 : struct tevent_timer *te,
464 : struct timeval t, void *ptr)
465 : {
466 0 : struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
467 : int i;
468 :
469 0 : DEBUG(SSSDBG_TRACE_FUNC, "Handling timeout\n");
470 :
471 0 : if (!ctx->services_started) {
472 :
473 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Providers did not start in time, "
474 : "forcing services startup!\n");
475 :
476 0 : ctx->services_started = true;
477 :
478 0 : DEBUG(SSSDBG_CONF_SETTINGS, "Now starting services!\n");
479 : /* then start all services */
480 0 : for (i = 0; ctx->services[i]; i++) {
481 0 : add_new_service(ctx, ctx->services[i], 0);
482 : }
483 : }
484 0 : }
485 :
486 0 : static int add_services_startup_timeout(struct mt_ctx *ctx)
487 : {
488 : struct tevent_timer *to;
489 : struct timeval tv;
490 :
491 : /* 5 seconds should be plenty */
492 0 : tv = tevent_timeval_current_ofs(5, 0);
493 0 : to = tevent_add_timer(ctx->ev, ctx, tv, services_startup_timeout, ctx);
494 0 : if (!to) {
495 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
496 0 : return ENOMEM;
497 : }
498 :
499 0 : return EOK;
500 : }
501 :
502 : struct mon_srv_iface monitor_methods = {
503 : { &mon_srv_iface_meta, 0 },
504 : .getVersion = get_monitor_version,
505 : .RegisterService = client_registration,
506 : };
507 :
508 : /* monitor_dbus_init
509 : * Set up the monitor service as a D-BUS Server */
510 0 : static int monitor_dbus_init(struct mt_ctx *ctx)
511 : {
512 : char *monitor_address;
513 : int ret;
514 :
515 0 : ret = monitor_get_sbus_address(ctx, &monitor_address);
516 0 : if (ret != EOK) {
517 0 : return ret;
518 : }
519 :
520 : /* If a service is running as unprivileged user, we need to make sure this
521 : * user can access the monitor sbus server. root is still king, so we don't
522 : * lose any access.
523 : */
524 0 : ret = sbus_new_server(ctx, ctx->ev, monitor_address, ctx->uid, ctx->gid,
525 : false, &ctx->sbus_srv, monitor_service_init, ctx);
526 :
527 0 : talloc_free(monitor_address);
528 :
529 0 : return ret;
530 : }
531 :
532 0 : static void tasks_check_handler(struct tevent_context *ev,
533 : struct tevent_timer *te,
534 : struct timeval t, void *ptr)
535 : {
536 0 : struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
537 : int ret;
538 :
539 0 : ret = service_send_ping(svc);
540 0 : switch (ret) {
541 : case EOK:
542 : /* all fine */
543 0 : break;
544 :
545 : case ENXIO:
546 0 : DEBUG(SSSDBG_CRIT_FAILURE,
547 : "Child (%s) not responding! (yet)\n", svc->name);
548 0 : break;
549 :
550 : default:
551 : /* TODO: should we tear it down ? */
552 0 : DEBUG(SSSDBG_CRIT_FAILURE,
553 : "Sending a message to service (%s) failed!!\n", svc->name);
554 0 : break;
555 : }
556 :
557 0 : if (svc->failed_pongs >= 3) {
558 : /* too long since we last heard of this process */
559 0 : DEBUG(SSSDBG_CRIT_FAILURE,
560 : "Killing service [%s], not responding to pings!\n",
561 : svc->name);
562 0 : sss_log(SSS_LOG_ERR,
563 : "Killing service [%s], not responding to pings!\n",
564 : svc->name);
565 :
566 : /* Kill the service. The SIGCHLD handler will restart it */
567 0 : monitor_kill_service(svc);
568 0 : return;
569 : }
570 :
571 : /* all fine, set up the task checker again */
572 0 : set_tasks_checker(svc);
573 : }
574 :
575 0 : static void set_tasks_checker(struct mt_svc *svc)
576 : {
577 0 : struct tevent_timer *te = NULL;
578 : struct timeval tv;
579 :
580 0 : gettimeofday(&tv, NULL);
581 0 : tv.tv_sec += svc->ping_time;
582 0 : tv.tv_usec = 0;
583 0 : te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, tasks_check_handler, svc);
584 0 : if (te == NULL) {
585 0 : DEBUG(SSSDBG_FATAL_FAILURE,
586 : "failed to add event, monitor offline for [%s]!\n",
587 : svc->name);
588 : /* FIXME: shutdown ? */
589 : }
590 0 : svc->ping_ev = te;
591 0 : }
592 :
593 : static void monitor_restart_service(struct mt_svc *svc);
594 : static void mt_svc_sigkill(struct tevent_context *ev,
595 : struct tevent_timer *te,
596 : struct timeval t, void *ptr);
597 0 : static int monitor_kill_service (struct mt_svc *svc)
598 : {
599 : int ret;
600 : struct timeval tv;
601 :
602 0 : ret = kill(svc->pid, SIGTERM);
603 0 : if (ret == -1) {
604 0 : ret = errno;
605 0 : DEBUG(SSSDBG_FATAL_FAILURE,
606 : "Sending signal to child (%s:%d) failed: [%d]: %s! "
607 : "Ignore and pretend child is dead.\n",
608 : svc->name, svc->pid, ret, strerror(ret));
609 : /* The only thing we can try here is to launch a new process
610 : * and hope that it works.
611 : */
612 0 : monitor_restart_service(svc);
613 0 : return EOK;
614 : }
615 :
616 : /* Set up a timer to send SIGKILL if this process
617 : * doesn't exit within sixty seconds
618 : */
619 0 : tv = tevent_timeval_current_ofs(svc->kill_time, 0);
620 0 : svc->kill_timer = tevent_add_timer(svc->mt_ctx->ev,
621 : svc,
622 : tv,
623 : mt_svc_sigkill,
624 : svc);
625 0 : if (svc->kill_timer == NULL) {
626 : /* Nothing much we can do */
627 0 : DEBUG(SSSDBG_CRIT_FAILURE,
628 : "Failed to allocate timed event: mt_svc_sigkill.\n");
629 : /* We'll just have to hope that the SIGTERM succeeds */
630 : }
631 :
632 0 : return EOK;
633 : }
634 :
635 0 : static void mt_svc_sigkill(struct tevent_context *ev,
636 : struct tevent_timer *te,
637 : struct timeval t, void *ptr)
638 : {
639 : int ret;
640 0 : struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
641 :
642 0 : DEBUG(SSSDBG_FATAL_FAILURE,
643 : "[%s][%d] is not responding to SIGTERM. Sending SIGKILL.\n",
644 : svc->name, svc->pid);
645 0 : sss_log(SSS_LOG_ERR,
646 : "[%s][%d] is not responding to SIGTERM. Sending SIGKILL.\n",
647 : svc->name, svc->pid);
648 :
649 : /* timer was succesfully executed and it will be released by tevent */
650 0 : svc->kill_timer = NULL;
651 :
652 0 : ret = kill(svc->pid, SIGKILL);
653 0 : if (ret != EOK) {
654 0 : ret = errno;
655 0 : DEBUG(SSSDBG_FATAL_FAILURE,
656 : "Sending signal to child (%s:%d) failed! "
657 : "Ignore and pretend child is dead.\n",
658 : svc->name, svc->pid);
659 :
660 0 : if (ret == ESRCH) {
661 : /* The process doesn't exist
662 : * This most likely means we hit a race where
663 : * the SIGTERM concluded just after the timer
664 : * fired but before we called kill() here.
665 : * We'll just do nothing, since the
666 : * mt_svc_exit_handler() should be doing the
667 : * necessary work.
668 : */
669 0 : return;
670 : }
671 :
672 : /* Something went really wrong.
673 : * The only thing we can try here is to launch a new process
674 : * and hope that it works.
675 : */
676 0 : monitor_restart_service(svc);
677 : }
678 :
679 : /* The process should terminate immediately and then be
680 : * restarted by the mt_svc_exit_handler()
681 : */
682 0 : return;
683 : }
684 :
685 0 : static void reload_reply(DBusPendingCall *pending, void *data)
686 : {
687 : DBusMessage *reply;
688 0 : struct mt_svc *svc = talloc_get_type(data, struct mt_svc);
689 :
690 0 : reply = dbus_pending_call_steal_reply(pending);
691 0 : if (!reply) {
692 : /* reply should never be null. This function shouldn't be called
693 : * until reply is valid or timeout has occurred. If reply is NULL
694 : * here, something is seriously wrong and we should bail out.
695 : */
696 0 : DEBUG(SSSDBG_FATAL_FAILURE,
697 : "A reply callback was called but no reply was received"
698 : " and no timeout occurred\n");
699 : /* Destroy this connection */
700 0 : sbus_disconnect(svc->conn);
701 0 : dbus_pending_call_unref(pending);
702 0 : return;
703 : }
704 :
705 : /* TODO: Handle cases where the call has timed out or returned
706 : * with an error.
707 : */
708 :
709 0 : dbus_pending_call_unref(pending);
710 0 : dbus_message_unref(reply);
711 : }
712 :
713 : static int service_signal_dns_reload(struct mt_svc *svc);
714 0 : static int monitor_update_resolv(struct config_file_ctx *file_ctx,
715 : const char *filename)
716 : {
717 : int ret;
718 : struct mt_svc *cur_svc;
719 0 : DEBUG(SSSDBG_OP_FAILURE, "Resolv.conf has been updated. Reloading.\n");
720 :
721 0 : ret = res_init();
722 0 : if(ret != 0) {
723 0 : return EIO;
724 : }
725 :
726 : /* Signal all services to reload their DNS configuration */
727 0 : for(cur_svc = file_ctx->mt_ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
728 0 : service_signal_dns_reload(cur_svc);
729 : }
730 0 : return EOK;
731 : }
732 :
733 0 : static int service_signal(struct mt_svc *svc, const char *svc_signal)
734 : {
735 : DBusMessage *msg;
736 : int ret;
737 :
738 0 : if (svc->provider && strcasecmp(svc->provider, "local") == 0) {
739 : /* The local provider requires no signaling */
740 0 : return EOK;
741 : }
742 :
743 0 : if (!svc->conn) {
744 : /* Avoid a race condition where we are trying to
745 : * order a service to reload that hasn't started
746 : * yet.
747 : */
748 0 : DEBUG(SSSDBG_CRIT_FAILURE,
749 : "Could not signal service [%s].\n", svc->name);
750 0 : return EIO;
751 : }
752 :
753 0 : msg = dbus_message_new_method_call(NULL,
754 : MONITOR_PATH,
755 : MON_CLI_IFACE,
756 : svc_signal);
757 0 : if (msg == NULL) {
758 0 : DEBUG(SSSDBG_FATAL_FAILURE,
759 : "Out of memory trying to allocate memory to invoke: %s\n",
760 : svc_signal);
761 0 : monitor_kill_service(svc);
762 0 : return ENOMEM;
763 : }
764 :
765 0 : ret = sbus_conn_send(svc->conn, msg,
766 0 : svc->mt_ctx->service_id_timeout,
767 : reload_reply, svc, NULL);
768 :
769 0 : dbus_message_unref(msg);
770 0 : return ret;
771 : }
772 :
773 0 : static int service_signal_dns_reload(struct mt_svc *svc)
774 : {
775 0 : return service_signal(svc, MON_CLI_IFACE_RESINIT);
776 : }
777 0 : static int service_signal_offline(struct mt_svc *svc)
778 : {
779 0 : return service_signal(svc, MON_CLI_IFACE_GOOFFLINE);
780 : }
781 0 : static int service_signal_reset_offline(struct mt_svc *svc)
782 : {
783 0 : return service_signal(svc, MON_CLI_IFACE_RESETOFFLINE);
784 : }
785 0 : static int service_signal_rotate(struct mt_svc *svc)
786 : {
787 0 : return service_signal(svc, MON_CLI_IFACE_ROTATELOGS);
788 : }
789 0 : static int service_signal_clear_memcache(struct mt_svc *svc)
790 : {
791 0 : return service_signal(svc, MON_CLI_IFACE_CLEARMEMCACHE);
792 : }
793 0 : static int service_signal_clear_enum_cache(struct mt_svc *svc)
794 : {
795 0 : return service_signal(svc, MON_CLI_IFACE_CLEARENUMCACHE);
796 : }
797 0 : static int service_signal_sysbus_reconnect(struct mt_svc *svc)
798 : {
799 0 : return service_signal(svc, MON_CLI_IFACE_SYSBUSRECONNECT);
800 : }
801 :
802 0 : static int check_domain_ranges(struct sss_domain_info *domains)
803 : {
804 0 : struct sss_domain_info *dom = domains, *other = NULL;
805 : uint32_t id_min, id_max;
806 :
807 0 : while (dom) {
808 0 : other = get_next_domain(dom, false);
809 0 : if (dom->id_max && dom->id_min > dom->id_max) {
810 0 : DEBUG(SSSDBG_CRIT_FAILURE,
811 : "Domain '%s' does not have a valid ID range\n", dom->name);
812 0 : return EINVAL;
813 : }
814 :
815 0 : while (other) {
816 0 : id_min = MAX(dom->id_min, other->id_min);
817 0 : id_max = MIN((dom->id_max ? dom->id_max : UINT32_MAX),
818 : (other->id_max ? other->id_max : UINT32_MAX));
819 0 : if (id_min <= id_max) {
820 0 : DEBUG(SSSDBG_MINOR_FAILURE,
821 : "Domains '%s' and '%s' overlap in range %u - %u\n",
822 : dom->name, other->name, id_min, id_max);
823 : }
824 0 : other = get_next_domain(other, false);
825 : }
826 0 : dom = get_next_domain(dom, false);
827 : }
828 :
829 0 : return EOK;
830 : }
831 :
832 0 : static int check_local_domain_unique(struct sss_domain_info *domains)
833 : {
834 0 : uint8_t count = 0;
835 :
836 0 : struct sss_domain_info *dom = domains;
837 :
838 0 : while (dom) {
839 0 : if (strcasecmp(dom->provider, "local") == 0) {
840 0 : count++;
841 : }
842 :
843 0 : if (count > 1) {
844 0 : break;
845 : }
846 :
847 0 : dom = get_next_domain(dom, false);
848 : }
849 :
850 0 : if (count > 1) {
851 0 : return EINVAL;
852 : }
853 :
854 0 : return EOK;
855 : }
856 :
857 0 : static errno_t add_implicit_services(struct confdb_ctx *cdb, TALLOC_CTX *mem_ctx,
858 : char ***_services)
859 : {
860 : int ret;
861 : char **domain_names;
862 : TALLOC_CTX *tmp_ctx;
863 : size_t c;
864 : char *conf_path;
865 : char *id_provider;
866 0 : bool add_pac = false;
867 :
868 0 : tmp_ctx = talloc_new(NULL);
869 0 : if (tmp_ctx == NULL) {
870 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
871 0 : return ENOMEM;
872 : }
873 :
874 0 : ret = confdb_get_string_as_list(cdb, tmp_ctx,
875 : CONFDB_MONITOR_CONF_ENTRY,
876 : CONFDB_MONITOR_ACTIVE_DOMAINS,
877 : &domain_names);
878 0 : if (ret == ENOENT) {
879 0 : DEBUG(SSSDBG_OP_FAILURE, "No domains configured!\n");
880 0 : goto done;
881 : }
882 :
883 0 : for (c = 0; domain_names[c] != NULL; c++) {
884 0 : conf_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL,
885 0 : domain_names[c]);
886 0 : if (conf_path == NULL) {
887 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
888 0 : ret = ENOMEM;
889 0 : goto done;
890 : }
891 :
892 0 : ret = confdb_get_string(cdb, tmp_ctx, conf_path,
893 : CONFDB_DOMAIN_ID_PROVIDER, NULL, &id_provider);
894 0 : if (ret == EOK) {
895 0 : if (id_provider == NULL) {
896 0 : DEBUG(SSSDBG_OP_FAILURE, "id_provider is not set for "
897 : "domain [%s], trying next domain.\n", domain_names[c]);
898 0 : continue;
899 : }
900 :
901 0 : if (strcasecmp(id_provider, "IPA") == 0) {
902 0 : add_pac = true;
903 : }
904 : } else {
905 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to get id_provider for " \
906 : "domain [%s], trying next domain.\n",
907 : domain_names[c]);
908 : }
909 : }
910 :
911 0 : if (BUILD_WITH_PAC_RESPONDER && add_pac &&
912 0 : !string_in_list("pac", *_services, false)) {
913 0 : ret = add_string_to_list(mem_ctx, "pac", _services);
914 0 : if (ret != EOK) {
915 0 : DEBUG(SSSDBG_OP_FAILURE, "add_string_to_list failed.\n");
916 0 : goto done;
917 : }
918 : }
919 :
920 0 : ret = EOK;
921 :
922 : done:
923 0 : talloc_free(tmp_ctx);
924 :
925 0 : return ret;
926 : }
927 :
928 0 : static char *check_services(char **services)
929 : {
930 0 : const char * const *known_services = get_known_services();
931 : int i;
932 : int ii;
933 :
934 : /* Check if services we are about to start are in the list if known */
935 0 : for (i = 0; services[i]; i++) {
936 0 : for (ii=0; known_services[ii]; ii++) {
937 0 : if (strcasecmp(services[i], known_services[ii]) == 0) {
938 0 : break;
939 : }
940 : }
941 :
942 0 : if (known_services[ii] == NULL) {
943 0 : return services[i];
944 : }
945 : }
946 :
947 0 : return NULL;
948 : }
949 :
950 0 : static int get_service_user(struct mt_ctx *ctx)
951 : {
952 : errno_t ret;
953 : char *user_str;
954 :
955 0 : ret = confdb_get_string(ctx->cdb, ctx, CONFDB_MONITOR_CONF_ENTRY,
956 : CONFDB_MONITOR_USER_RUNAS,
957 : SSSD_USER, &user_str);
958 0 : if (ret != EOK) {
959 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get the user to run as\n");
960 0 : return ret;
961 : }
962 :
963 0 : ret = sss_user_by_name_or_uid(user_str, &ctx->uid, &ctx->gid);
964 0 : talloc_free(user_str);
965 0 : if (ret != EOK) {
966 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n");
967 0 : return ret;
968 : }
969 :
970 0 : return EOK;
971 : }
972 :
973 0 : static int get_monitor_config(struct mt_ctx *ctx)
974 : {
975 : int ret;
976 : int timeout_seconds;
977 0 : char *badsrv = NULL;
978 : int i;
979 :
980 0 : ret = confdb_get_int(ctx->cdb,
981 : CONFDB_MONITOR_CONF_ENTRY,
982 : CONFDB_MONITOR_SBUS_TIMEOUT,
983 : 10, &timeout_seconds);
984 0 : if (ret != EOK) {
985 0 : return ret;
986 : }
987 :
988 0 : ctx->service_id_timeout = timeout_seconds * 1000; /* service_id_timeout is in ms */
989 :
990 0 : ret = confdb_get_string_as_list(ctx->cdb, ctx,
991 : CONFDB_MONITOR_CONF_ENTRY,
992 : CONFDB_MONITOR_ACTIVE_SERVICES,
993 : &ctx->services);
994 0 : if (ret != EOK) {
995 0 : DEBUG(SSSDBG_FATAL_FAILURE, "No services configured!\n");
996 0 : return EINVAL;
997 : }
998 :
999 0 : ret = add_implicit_services(ctx->cdb, ctx, &ctx->services);
1000 0 : if (ret != EOK) {
1001 0 : DEBUG(SSSDBG_OP_FAILURE, "Failed to add implicit configured "
1002 : "services. Some functionality might "
1003 : "be missing\n");
1004 : }
1005 :
1006 0 : badsrv = check_services(ctx->services);
1007 0 : if (badsrv != NULL) {
1008 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Invalid service %s\n", badsrv);
1009 0 : return EINVAL;
1010 : }
1011 :
1012 0 : ctx->started_services = 0;
1013 0 : ctx->num_services = 0;
1014 0 : for (i = 0; ctx->services[i] != NULL; i++) {
1015 0 : ctx->num_services++;
1016 : }
1017 :
1018 0 : ret = get_service_user(ctx);
1019 0 : if (ret != EOK) {
1020 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get the unprivileged user\n");
1021 0 : return ret;
1022 : }
1023 :
1024 0 : ret = confdb_get_domains(ctx->cdb, &ctx->domains);
1025 0 : if (ret != EOK) {
1026 0 : DEBUG(SSSDBG_FATAL_FAILURE, "No domains configured.\n");
1027 0 : return ret;
1028 : }
1029 :
1030 0 : ret = check_local_domain_unique(ctx->domains);
1031 0 : if (ret != EOK) {
1032 0 : DEBUG(SSSDBG_FATAL_FAILURE, "More than one local domain configured.\n");
1033 0 : return ret;
1034 : }
1035 :
1036 : /* Check UID/GID overlaps */
1037 0 : ret = check_domain_ranges(ctx->domains);
1038 0 : if (ret != EOK) {
1039 0 : return ret;
1040 : }
1041 :
1042 0 : return EOK;
1043 : }
1044 :
1045 0 : static errno_t get_ping_config(struct mt_ctx *ctx, const char *path,
1046 : struct mt_svc *svc)
1047 : {
1048 : errno_t ret;
1049 :
1050 0 : ret = confdb_get_int(ctx->cdb, path,
1051 : CONFDB_DOMAIN_TIMEOUT,
1052 : MONITOR_DEF_PING_TIME, &svc->ping_time);
1053 0 : if (ret != EOK) {
1054 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1055 : "Failed to get ping timeout for '%s'\n", svc->name);
1056 0 : return ret;
1057 : }
1058 :
1059 : /* 'timeout = 0' should be translated to the default */
1060 0 : if (svc->ping_time == 0) {
1061 0 : svc->ping_time = MONITOR_DEF_PING_TIME;
1062 : }
1063 :
1064 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1065 : "Time between service pings for [%s]: [%d]\n",
1066 : svc->name, svc->ping_time);
1067 :
1068 0 : ret = confdb_get_int(ctx->cdb, path,
1069 : CONFDB_SERVICE_FORCE_TIMEOUT,
1070 : MONITOR_DEF_FORCE_TIME, &svc->kill_time);
1071 0 : if (ret != EOK) {
1072 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1073 : "Failed to get kill timeout for %s\n", svc->name);
1074 0 : return ret;
1075 : }
1076 :
1077 : /* 'force_timeout = 0' should be translated to the default */
1078 0 : if (svc->kill_time == 0) {
1079 0 : svc->kill_time = MONITOR_DEF_FORCE_TIME;
1080 : }
1081 :
1082 0 : DEBUG(SSSDBG_CONF_SETTINGS,
1083 : "Time between SIGTERM and SIGKILL for [%s]: [%d]\n",
1084 : svc->name, svc->kill_time);
1085 :
1086 0 : return EOK;
1087 : }
1088 :
1089 : /* This is a temporary function that returns false if the service
1090 : * being started was only tested when running as root.
1091 : */
1092 0 : static bool svc_supported_as_nonroot(const char *svc_name)
1093 : {
1094 0 : if ((strcmp(svc_name, "nss") == 0)
1095 0 : || (strcmp(svc_name, "pam") == 0)
1096 0 : || (strcmp(svc_name, "autofs") == 0)
1097 0 : || (strcmp(svc_name, "pac") == 0)
1098 0 : || (strcmp(svc_name, "sudo") == 0)
1099 0 : || (strcmp(svc_name, "ssh") == 0)) {
1100 0 : return true;
1101 : }
1102 0 : return false;
1103 : }
1104 :
1105 0 : static int get_service_config(struct mt_ctx *ctx, const char *name,
1106 : struct mt_svc **svc_cfg)
1107 : {
1108 : int ret;
1109 : char *path;
1110 : struct mt_svc *svc;
1111 0 : time_t now = time(NULL);
1112 0 : uid_t uid = 0;
1113 0 : gid_t gid = 0;
1114 :
1115 0 : *svc_cfg = NULL;
1116 :
1117 0 : svc = talloc_zero(ctx, struct mt_svc);
1118 0 : if (!svc) {
1119 0 : return ENOMEM;
1120 : }
1121 0 : svc->mt_ctx = ctx;
1122 0 : svc->type = MT_SVC_SERVICE;
1123 :
1124 0 : talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
1125 :
1126 0 : svc->name = talloc_strdup(svc, name);
1127 0 : if (!svc->name) {
1128 0 : talloc_free(svc);
1129 0 : return ENOMEM;
1130 : }
1131 :
1132 0 : svc->identity = talloc_strdup(svc, name);
1133 0 : if (!svc->identity) {
1134 0 : talloc_free(svc);
1135 0 : return ENOMEM;
1136 : }
1137 :
1138 0 : path = talloc_asprintf(svc, CONFDB_SERVICE_PATH_TMPL, svc->name);
1139 0 : if (!path) {
1140 0 : talloc_free(svc);
1141 0 : return ENOMEM;
1142 : }
1143 :
1144 0 : ret = confdb_get_string(ctx->cdb, svc, path,
1145 : CONFDB_SERVICE_COMMAND,
1146 : NULL, &svc->command);
1147 0 : if (ret != EOK) {
1148 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Failed to start service '%s'\n", svc->name);
1149 0 : talloc_free(svc);
1150 0 : return ret;
1151 : }
1152 :
1153 0 : if (svc_supported_as_nonroot(svc->name)) {
1154 0 : uid = ctx->uid;
1155 0 : gid = ctx->gid;
1156 : }
1157 :
1158 0 : if (!svc->command) {
1159 0 : svc->command = talloc_asprintf(
1160 : svc, "%s/sssd_%s", SSSD_LIBEXEC_PATH, svc->name
1161 : );
1162 0 : if (!svc->command) {
1163 0 : talloc_free(svc);
1164 0 : return ENOMEM;
1165 : }
1166 :
1167 0 : svc->command = talloc_asprintf_append(svc->command,
1168 : " --uid %"SPRIuid" --gid %"SPRIgid,
1169 : uid, gid);
1170 0 : if (!svc->command) {
1171 0 : talloc_free(svc);
1172 0 : return ENOMEM;
1173 : }
1174 :
1175 0 : if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
1176 0 : svc->command = talloc_asprintf_append(
1177 : svc->command, " -d %#.4x", cmdline_debug_level
1178 : );
1179 0 : if (!svc->command) {
1180 0 : talloc_free(svc);
1181 0 : return ENOMEM;
1182 : }
1183 : }
1184 :
1185 0 : if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
1186 0 : svc->command = talloc_asprintf_append(
1187 : svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
1188 : );
1189 0 : if (!svc->command) {
1190 0 : talloc_free(svc);
1191 0 : return ENOMEM;
1192 : }
1193 : }
1194 :
1195 0 : if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
1196 0 : svc->command = talloc_asprintf_append(
1197 : svc->command, " --debug-microseconds=%d",
1198 : cmdline_debug_microseconds
1199 : );
1200 0 : if (!svc->command) {
1201 0 : talloc_free(svc);
1202 0 : return ENOMEM;
1203 : }
1204 : }
1205 :
1206 0 : if (debug_to_file) {
1207 0 : svc->command = talloc_strdup_append(
1208 : svc->command, " --debug-to-files"
1209 : );
1210 0 : if (!svc->command) {
1211 0 : talloc_free(svc);
1212 0 : return ENOMEM;
1213 : }
1214 0 : } else if (ctx->is_daemon == false) {
1215 0 : svc->command = talloc_strdup_append(
1216 : svc->command, " --debug-to-stderr"
1217 : );
1218 0 : if (!svc->command) {
1219 0 : talloc_free(svc);
1220 0 : return ENOMEM;
1221 : }
1222 : }
1223 : }
1224 :
1225 0 : ret = get_ping_config(ctx, path, svc);
1226 0 : if (ret != EOK) {
1227 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1228 : "Failed to get ping timeouts for %s\n", svc->name);
1229 0 : talloc_free(svc);
1230 0 : return ret;
1231 : }
1232 :
1233 0 : svc->last_restart = now;
1234 :
1235 0 : *svc_cfg = svc;
1236 0 : talloc_free(path);
1237 :
1238 0 : return EOK;
1239 : }
1240 :
1241 0 : static int add_new_service(struct mt_ctx *ctx,
1242 : const char *name,
1243 : int restarts)
1244 : {
1245 : int ret;
1246 : struct mt_svc *svc;
1247 :
1248 0 : ret = get_service_config(ctx, name, &svc);
1249 0 : if (ret != EOK) {
1250 0 : return ret;
1251 : }
1252 0 : svc->restarts = restarts;
1253 :
1254 0 : ret = start_service(svc);
1255 0 : if (ret != EOK) {
1256 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Failed to start service '%s'\n", svc->name);
1257 0 : talloc_free(svc);
1258 : }
1259 :
1260 0 : return ret;
1261 : }
1262 :
1263 0 : static int get_provider_config(struct mt_ctx *ctx, const char *name,
1264 : struct mt_svc **svc_cfg)
1265 : {
1266 : int ret;
1267 : char *path;
1268 : struct mt_svc *svc;
1269 0 : time_t now = time(NULL);
1270 :
1271 0 : *svc_cfg = NULL;
1272 :
1273 0 : svc = talloc_zero(ctx, struct mt_svc);
1274 0 : if (!svc) {
1275 0 : return ENOMEM;
1276 : }
1277 0 : svc->mt_ctx = ctx;
1278 0 : svc->type = MT_SVC_PROVIDER;
1279 :
1280 0 : talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
1281 :
1282 0 : svc->name = talloc_strdup(svc, name);
1283 0 : if (!svc->name) {
1284 0 : talloc_free(svc);
1285 0 : return ENOMEM;
1286 : }
1287 :
1288 0 : svc->identity = talloc_asprintf(svc, "%%BE_%s", svc->name);
1289 0 : if (!svc->identity) {
1290 0 : talloc_free(svc);
1291 0 : return ENOMEM;
1292 : }
1293 :
1294 0 : path = talloc_asprintf(svc, CONFDB_DOMAIN_PATH_TMPL, name);
1295 0 : if (!path) {
1296 0 : talloc_free(svc);
1297 0 : return ENOMEM;
1298 : }
1299 :
1300 0 : ret = confdb_get_string(ctx->cdb, svc, path,
1301 : CONFDB_DOMAIN_ID_PROVIDER,
1302 : NULL, &svc->provider);
1303 0 : if (ret != EOK) {
1304 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1305 : "Failed to find ID provider from [%s] configuration\n", name);
1306 0 : talloc_free(svc);
1307 0 : return ret;
1308 : }
1309 :
1310 0 : ret = confdb_get_string(ctx->cdb, svc, path,
1311 : CONFDB_DOMAIN_COMMAND,
1312 : NULL, &svc->command);
1313 0 : if (ret != EOK) {
1314 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1315 : "Failed to find command from [%s] configuration\n", name);
1316 0 : talloc_free(svc);
1317 0 : return ret;
1318 : }
1319 :
1320 0 : ret = get_ping_config(ctx, path, svc);
1321 0 : if (ret != EOK) {
1322 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1323 : "Failed to get ping timeouts for %s\n", svc->name);
1324 0 : talloc_free(svc);
1325 0 : return ret;
1326 : }
1327 :
1328 0 : talloc_free(path);
1329 :
1330 : /* if no provider is present do not run the domain */
1331 0 : if (!svc->provider) {
1332 0 : talloc_free(svc);
1333 0 : return EIO;
1334 : }
1335 :
1336 : /* if there are no custom commands, build a default one */
1337 0 : if (!svc->command) {
1338 0 : svc->command = talloc_asprintf(
1339 : svc, "%s/sssd_be --domain %s", SSSD_LIBEXEC_PATH, svc->name
1340 : );
1341 0 : if (!svc->command) {
1342 0 : talloc_free(svc);
1343 0 : return ENOMEM;
1344 : }
1345 :
1346 0 : svc->command = talloc_asprintf_append(svc->command,
1347 : " --uid %"SPRIuid" --gid %"SPRIgid,
1348 : ctx->uid, ctx->gid);
1349 0 : if (!svc->command) {
1350 0 : talloc_free(svc);
1351 0 : return ENOMEM;
1352 : }
1353 :
1354 0 : if (cmdline_debug_level != SSSDBG_UNRESOLVED) {
1355 0 : svc->command = talloc_asprintf_append(
1356 : svc->command, " -d %#.4x", cmdline_debug_level
1357 : );
1358 0 : if (!svc->command) {
1359 0 : talloc_free(svc);
1360 0 : return ENOMEM;
1361 : }
1362 : }
1363 :
1364 0 : if (cmdline_debug_timestamps != SSSDBG_TIMESTAMP_UNRESOLVED) {
1365 0 : svc->command = talloc_asprintf_append(
1366 : svc->command, " --debug-timestamps=%d", cmdline_debug_timestamps
1367 : );
1368 0 : if (!svc->command) {
1369 0 : talloc_free(svc);
1370 0 : return ENOMEM;
1371 : }
1372 : }
1373 :
1374 0 : if (cmdline_debug_microseconds != SSSDBG_MICROSECONDS_UNRESOLVED) {
1375 0 : svc->command = talloc_asprintf_append(
1376 : svc->command, " --debug-microseconds=%d",
1377 : cmdline_debug_microseconds
1378 : );
1379 0 : if (!svc->command) {
1380 0 : talloc_free(svc);
1381 0 : return ENOMEM;
1382 : }
1383 : }
1384 :
1385 0 : if (debug_to_file) {
1386 0 : svc->command = talloc_strdup_append(
1387 : svc->command, " --debug-to-files"
1388 : );
1389 0 : if (!svc->command) {
1390 0 : talloc_free(svc);
1391 0 : return ENOMEM;
1392 : }
1393 0 : } else if (ctx->is_daemon == false) {
1394 0 : svc->command = talloc_strdup_append(
1395 : svc->command, " --debug-to-stderr"
1396 : );
1397 0 : if (!svc->command) {
1398 0 : talloc_free(svc);
1399 0 : return ENOMEM;
1400 : }
1401 : }
1402 : }
1403 :
1404 0 : svc->last_restart = now;
1405 :
1406 0 : *svc_cfg = svc;
1407 0 : return EOK;
1408 : }
1409 :
1410 0 : static int add_new_provider(struct mt_ctx *ctx,
1411 : const char *name,
1412 : int restarts)
1413 : {
1414 : int ret;
1415 : struct mt_svc *svc;
1416 :
1417 0 : ret = get_provider_config(ctx, name, &svc);
1418 0 : if (ret != EOK) {
1419 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1420 : "Could not get provider configuration for [%s]\n",
1421 : name);
1422 0 : return ret;
1423 : }
1424 0 : svc->restarts = restarts;
1425 :
1426 0 : if (strcasecmp(svc->provider, "local") == 0) {
1427 : /* The LOCAL provider requires no back-end currently
1428 : * We'll add it to the service list, but we don't need
1429 : * to poll it.
1430 : */
1431 0 : svc->svc_started = true;
1432 0 : DLIST_ADD(ctx->svc_list, svc);
1433 0 : return ENOENT;
1434 : }
1435 :
1436 0 : ret = start_service(svc);
1437 0 : if (ret != EOK) {
1438 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Failed to start service '%s'\n", svc->name);
1439 0 : talloc_free(svc);
1440 : }
1441 :
1442 0 : return ret;
1443 : }
1444 :
1445 0 : static void monitor_hup(struct tevent_context *ev,
1446 : struct tevent_signal *se,
1447 : int signum,
1448 : int count,
1449 : void *siginfo,
1450 : void *private_data)
1451 : {
1452 0 : struct mt_ctx *ctx = talloc_get_type(private_data, struct mt_ctx);
1453 : struct mt_svc *cur_svc;
1454 :
1455 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Received SIGHUP.\n");
1456 :
1457 : /* Send D-Bus message to other services to rotate their logs.
1458 : * NSS service receives also message to clear memory caches. */
1459 0 : for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
1460 0 : service_signal_rotate(cur_svc);
1461 0 : if (!strcmp(NSS_SBUS_SERVICE_NAME, cur_svc->name)) {
1462 0 : service_signal_clear_memcache(cur_svc);
1463 0 : service_signal_clear_enum_cache(cur_svc);
1464 : }
1465 :
1466 0 : if (!strcmp(SSS_AUTOFS_SBUS_SERVICE_NAME, cur_svc->name)) {
1467 0 : service_signal_clear_enum_cache(cur_svc);
1468 : }
1469 :
1470 : }
1471 :
1472 0 : }
1473 :
1474 0 : static int monitor_cleanup(void)
1475 : {
1476 : int ret;
1477 :
1478 0 : errno = 0;
1479 0 : ret = unlink(SSSD_PIDFILE_PATH);
1480 0 : if (ret == -1) {
1481 0 : ret = errno;
1482 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1483 : "Error removing pidfile! (%d [%s])\n", ret, strerror(ret));
1484 0 : return ret;
1485 : }
1486 :
1487 0 : return EOK;
1488 : }
1489 :
1490 0 : static void monitor_quit(struct mt_ctx *mt_ctx, int ret)
1491 : {
1492 : struct mt_svc *svc;
1493 : pid_t pid;
1494 : int status;
1495 : errno_t error;
1496 : int kret;
1497 : bool killed;
1498 :
1499 0 : DEBUG(SSSDBG_IMPORTANT_INFO, "Returned with: %d\n", ret);
1500 :
1501 : /* Kill all of our known children manually */
1502 0 : DLIST_FOR_EACH(svc, mt_ctx->svc_list) {
1503 0 : if (svc->pid == 0) {
1504 : /* The local provider has no PID */
1505 0 : continue;
1506 : }
1507 :
1508 0 : killed = false;
1509 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1510 : "Terminating [%s][%d]\n", svc->name, svc->pid);
1511 : do {
1512 0 : errno = 0;
1513 0 : kret = kill(svc->pid, SIGTERM);
1514 0 : if (kret < 0) {
1515 0 : error = errno;
1516 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Couldn't kill [%s][%d]: [%s]\n",
1517 : svc->name, svc->pid, strerror(error));
1518 : }
1519 :
1520 0 : error = 0;
1521 : do {
1522 0 : errno = 0;
1523 0 : pid = waitpid(svc->pid, &status, WNOHANG);
1524 0 : if (pid == -1) {
1525 : /* An error occurred while waiting */
1526 0 : error = errno;
1527 0 : if (error == ECHILD) {
1528 0 : killed = true;
1529 0 : } else if (error != EINTR) {
1530 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1531 : "[%d][%s] while waiting for [%s]\n",
1532 : error, strerror(error), svc->name);
1533 : /* Forcibly kill this child */
1534 0 : kill(svc->pid, SIGKILL);
1535 0 : break;
1536 : }
1537 0 : } else if (pid != 0) {
1538 0 : error = 0;
1539 0 : if (WIFEXITED(status)) {
1540 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1541 : "Child [%s] exited gracefully\n", svc->name);
1542 0 : } else if (WIFSIGNALED(status)) {
1543 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1544 : "Child [%s] terminated with a signal\n", svc->name);
1545 : } else {
1546 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1547 : "Child [%s] did not exit cleanly\n", svc->name);
1548 : /* Forcibly kill this child */
1549 0 : kill(svc->pid, SIGKILL);
1550 : }
1551 0 : killed = true;
1552 : }
1553 0 : } while (error == EINTR);
1554 0 : if (!killed) {
1555 : /* Sleep 10ms and try again */
1556 0 : usleep(10000);
1557 : }
1558 0 : } while (!killed);
1559 : }
1560 :
1561 : #if HAVE_GETPGRP
1562 : /* Kill any remaining children in our process group, just in case
1563 : * we have any leftover children we don't expect. For example, if
1564 : * a krb5_child or ldap_child is running at the same moment.
1565 : */
1566 0 : error = 0;
1567 0 : if (getpgrp() == getpid()) {
1568 0 : kill(-getpgrp(), SIGTERM);
1569 : do {
1570 0 : errno = 0;
1571 0 : pid = waitpid(0, &status, 0);
1572 0 : if (pid == -1) {
1573 0 : error = errno;
1574 : }
1575 0 : } while (error == EINTR || pid > 0);
1576 : }
1577 : #endif
1578 :
1579 0 : monitor_cleanup();
1580 :
1581 0 : exit(ret);
1582 : }
1583 :
1584 0 : static void monitor_quit_signal(struct tevent_context *ev,
1585 : struct tevent_signal *se,
1586 : int signum,
1587 : int count,
1588 : void *siginfo,
1589 : void *private_data)
1590 : {
1591 0 : struct mt_ctx *mt_ctx = talloc_get_type(private_data, struct mt_ctx);
1592 :
1593 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Received shutdown command\n");
1594 :
1595 0 : DEBUG(SSSDBG_IMPORTANT_INFO, "Monitor received %s: terminating "
1596 : "children\n", strsignal(signum));
1597 :
1598 0 : monitor_quit(mt_ctx, 0);
1599 0 : }
1600 :
1601 0 : static void signal_res_init(struct mt_ctx *monitor)
1602 : {
1603 : struct mt_svc *cur_svc;
1604 : int ret;
1605 0 : DEBUG(SSSDBG_OP_FAILURE, "Reloading Resolv.conf.\n");
1606 :
1607 0 : ret = res_init();
1608 0 : if (ret == 0) {
1609 0 : for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
1610 0 : service_signal_dns_reload(cur_svc);
1611 : }
1612 : }
1613 0 : }
1614 :
1615 0 : static void signal_offline(struct tevent_context *ev,
1616 : struct tevent_signal *se,
1617 : int signum,
1618 : int count,
1619 : void *siginfo,
1620 : void *private_data)
1621 : {
1622 : struct mt_ctx *monitor;
1623 : struct mt_svc *cur_svc;
1624 :
1625 0 : monitor = talloc_get_type(private_data, struct mt_ctx);
1626 :
1627 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
1628 : "Signaling providers to go offline immediately.\n");
1629 :
1630 : /* Signal all providers to immediately go offline */
1631 0 : for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
1632 : /* Don't signal services, only providers */
1633 0 : if (cur_svc->provider) {
1634 0 : service_signal_offline(cur_svc);
1635 : }
1636 : }
1637 0 : }
1638 :
1639 0 : static void signal_offline_reset(struct tevent_context *ev,
1640 : struct tevent_signal *se,
1641 : int signum,
1642 : int count,
1643 : void *siginfo,
1644 : void *private_data)
1645 : {
1646 : struct mt_ctx *monitor;
1647 : struct mt_svc *cur_svc;
1648 :
1649 0 : monitor = talloc_get_type(private_data, struct mt_ctx);
1650 :
1651 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
1652 : "Signaling providers to reset offline immediately.\n");
1653 :
1654 0 : for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
1655 0 : if (cur_svc->provider) {
1656 0 : service_signal_reset_offline(cur_svc);
1657 : }
1658 :
1659 0 : if (strcmp(SSS_IFP_SBUS_SERVICE_NAME, cur_svc->name) == 0) {
1660 0 : service_signal_sysbus_reconnect(cur_svc);
1661 : }
1662 : }
1663 0 : signal_res_init(monitor);
1664 0 : }
1665 :
1666 0 : static int monitor_ctx_destructor(void *mem)
1667 : {
1668 0 : struct mt_ctx *mon = talloc_get_type(mem, struct mt_ctx);
1669 : struct mt_svc *svc;
1670 :
1671 : /* zero out references in svcs so that they don't try
1672 : * to access the monitor context on process shutdown */
1673 :
1674 0 : for (svc = mon->svc_list; svc; svc = svc->next) {
1675 0 : svc->mt_ctx = NULL;
1676 : }
1677 0 : return 0;
1678 : }
1679 :
1680 : /*
1681 : * This function should not be static otherwise gcc does some special kind of
1682 : * optimisations which should not happen according to code: chown (unlink)
1683 : * failed (return -1) but errno was zero.
1684 : * As a result of this * warning is printed ‘monitor’ may be used
1685 : * uninitialized in this function. Instead of checking errno for 0
1686 : * it's better to disable optimisation(in-lining) of this function.
1687 : */
1688 0 : errno_t load_configuration(TALLOC_CTX *mem_ctx,
1689 : const char *config_file,
1690 : struct mt_ctx **monitor)
1691 : {
1692 : errno_t ret;
1693 : struct mt_ctx *ctx;
1694 0 : char *cdb_file = NULL;
1695 :
1696 0 : ctx = talloc_zero(mem_ctx, struct mt_ctx);
1697 0 : if(!ctx) {
1698 0 : return ENOMEM;
1699 : }
1700 :
1701 0 : talloc_set_destructor((TALLOC_CTX *)ctx, monitor_ctx_destructor);
1702 :
1703 0 : cdb_file = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
1704 0 : if (cdb_file == NULL) {
1705 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory, aborting!\n");
1706 0 : ret = ENOMEM;
1707 0 : goto done;
1708 : }
1709 :
1710 0 : ret = confdb_init(ctx, &ctx->cdb, cdb_file);
1711 0 : if (ret != EOK) {
1712 0 : DEBUG(SSSDBG_FATAL_FAILURE,"The confdb initialization failed\n");
1713 0 : goto done;
1714 : }
1715 :
1716 : /* Initialize the CDB from the configuration file */
1717 0 : ret = confdb_test(ctx->cdb);
1718 0 : if (ret == ENOENT) {
1719 : /* First-time setup */
1720 :
1721 : /* Purge any existing confdb in case an old
1722 : * misconfiguration gets in the way
1723 : */
1724 0 : talloc_zfree(ctx->cdb);
1725 0 : ret = unlink(cdb_file);
1726 0 : if (ret != EOK && errno != ENOENT) {
1727 0 : ret = errno;
1728 0 : DEBUG(SSSDBG_MINOR_FAILURE,
1729 : "Purging existing confdb failed: %d [%s].\n",
1730 : ret, sss_strerror(ret));
1731 0 : goto done;
1732 : }
1733 :
1734 0 : ret = confdb_init(ctx, &ctx->cdb, cdb_file);
1735 0 : if (ret != EOK) {
1736 0 : DEBUG(SSSDBG_FATAL_FAILURE,"The confdb initialization failed\n");
1737 0 : goto done;
1738 : }
1739 :
1740 : /* Load special entries */
1741 0 : ret = confdb_create_base(ctx->cdb);
1742 0 : if (ret != EOK) {
1743 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1744 : "Unable to load special entries into confdb\n");
1745 0 : goto done;
1746 : }
1747 0 : } else if (ret != EOK) {
1748 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Fatal error initializing confdb\n");
1749 0 : goto done;
1750 : }
1751 :
1752 0 : ret = confdb_init_db(config_file, ctx->cdb);
1753 0 : if (ret != EOK) {
1754 0 : DEBUG(SSSDBG_FATAL_FAILURE, "ConfDB initialization has failed [%s]\n",
1755 : sss_strerror(ret));
1756 0 : goto done;
1757 : }
1758 :
1759 : /* Validate the configuration in the database */
1760 : /* Read in the monitor's configuration */
1761 0 : ret = get_monitor_config(ctx);
1762 0 : if (ret != EOK) {
1763 0 : goto done;
1764 : }
1765 :
1766 : /* Allow configuration database to be accessible
1767 : * when SSSD runs as nonroot */
1768 0 : ret = chown(cdb_file, ctx->uid, ctx->gid);
1769 0 : if (ret != 0) {
1770 0 : ret = errno;
1771 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1772 : "chown failed for [%s]: [%d][%s].\n",
1773 : cdb_file, ret, sss_strerror(ret));
1774 0 : goto done;
1775 : }
1776 :
1777 0 : *monitor = ctx;
1778 :
1779 0 : ret = EOK;
1780 :
1781 : done:
1782 0 : talloc_free(cdb_file);
1783 0 : if (ret != EOK) {
1784 0 : talloc_free(ctx);
1785 : }
1786 0 : return ret;
1787 : }
1788 :
1789 : static errno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
1790 : struct mt_ctx *ctx,
1791 : const char *file,
1792 : monitor_reconf_fn fn,
1793 : bool ignore_missing);
1794 :
1795 : #ifdef HAVE_INOTIFY
1796 : static void process_config_file(struct tevent_context *ev,
1797 : struct tevent_timer *te,
1798 : struct timeval t, void *ptr);
1799 :
1800 0 : static void config_file_changed(struct tevent_context *ev,
1801 : struct tevent_fd *fde,
1802 : uint16_t flags, void *data)
1803 : {
1804 0 : struct tevent_timer *te = NULL;
1805 : struct timeval tv;
1806 : struct config_file_ctx *file_ctx;
1807 :
1808 0 : file_ctx = talloc_get_type(data, struct config_file_ctx);
1809 0 : if (file_ctx->needs_update) {
1810 : /* Skip updating. It's already queued for update.
1811 : */
1812 0 : return;
1813 : }
1814 :
1815 : /* We will queue the file for update in one second.
1816 : * This way, if there is a script writing to the file
1817 : * repeatedly, we won't be attempting to update multiple
1818 : * times.
1819 : */
1820 0 : gettimeofday(&tv, NULL);
1821 0 : tv.tv_sec += 1;
1822 :
1823 0 : te = tevent_add_timer(ev, ev, tv, process_config_file, file_ctx);
1824 0 : if (!te) {
1825 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1826 : "Unable to queue config file update! Exiting.\n");
1827 0 : kill(getpid(), SIGTERM);
1828 0 : return;
1829 : }
1830 0 : file_ctx->needs_update = 1;
1831 : }
1832 :
1833 : struct rewatch_ctx {
1834 : struct config_file_callback *cb;
1835 : struct config_file_ctx *file_ctx;
1836 : };
1837 : static void rewatch_config_file(struct tevent_context *ev,
1838 : struct tevent_timer *te,
1839 : struct timeval t, void *ptr);
1840 0 : static void process_config_file(struct tevent_context *ev,
1841 : struct tevent_timer *te,
1842 : struct timeval t, void *ptr)
1843 : {
1844 : TALLOC_CTX *tmp_ctx;
1845 : struct inotify_event *in_event;
1846 : char *name;
1847 : ssize_t len;
1848 : struct config_file_ctx *file_ctx;
1849 : struct config_file_callback *cb;
1850 : struct rewatch_ctx *rw_ctx;
1851 : errno_t ret;
1852 :
1853 0 : file_ctx = talloc_get_type(ptr, struct config_file_ctx);
1854 :
1855 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Processing config file changes\n");
1856 :
1857 0 : tmp_ctx = talloc_new(NULL);
1858 0 : if (!tmp_ctx) return;
1859 :
1860 0 : in_event = talloc(tmp_ctx, struct inotify_event);
1861 0 : if (!in_event) {
1862 0 : goto done;
1863 : }
1864 :
1865 0 : errno = 0;
1866 0 : len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, in_event,
1867 : sizeof(struct inotify_event));
1868 0 : if (len == -1) {
1869 0 : ret = errno;
1870 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1871 : "Critical error reading inotify file descriptor [%d]: %s\n",
1872 : ret, strerror(ret));
1873 0 : goto done;
1874 : }
1875 :
1876 0 : if (in_event->len > 0) {
1877 : /* Read in the name, even though we don't use it,
1878 : * so that read ptr is in the right place
1879 : */
1880 0 : name = talloc_size(tmp_ctx, in_event->len);
1881 0 : if (!name) {
1882 0 : goto done;
1883 : }
1884 :
1885 0 : errno = 0;
1886 0 : len = sss_atomic_read_s(file_ctx->mt_ctx->inotify_fd, name, in_event->len);
1887 0 : if (len == -1) {
1888 0 : ret = errno;
1889 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1890 : "Critical error reading inotify file descriptor [%d]: %s\n",
1891 : ret, strerror(ret));
1892 0 : goto done;
1893 : }
1894 : }
1895 :
1896 0 : for (cb = file_ctx->callbacks; cb; cb = cb->next) {
1897 0 : if (cb->wd == in_event->wd) {
1898 0 : break;
1899 : }
1900 : }
1901 0 : if (!cb) {
1902 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Unknown watch descriptor\n");
1903 0 : goto done;
1904 : }
1905 :
1906 0 : if (in_event->mask & IN_IGNORED) {
1907 : /* Some text editors will move a new file on top of the
1908 : * existing one instead of modifying it. In this case,
1909 : * the kernel will send us an IN_IGNORE signal.
1910 : * We will try to open a new watch descriptor on the
1911 : * new file.
1912 : */
1913 : struct timeval tv;
1914 : struct tevent_timer *tev;
1915 0 : tv.tv_sec = t.tv_sec+5;
1916 0 : tv.tv_usec = t.tv_usec;
1917 0 : DEBUG(SSSDBG_FUNC_DATA, "Restoring inotify watch.\n");
1918 :
1919 0 : cb->retries = 0;
1920 0 : rw_ctx = talloc(file_ctx, struct rewatch_ctx);
1921 0 : if(!rw_ctx) {
1922 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1923 : "Could not restore inotify watch. Quitting!\n");
1924 0 : close(file_ctx->mt_ctx->inotify_fd);
1925 0 : kill(getpid(), SIGTERM);
1926 0 : goto done;
1927 : }
1928 0 : rw_ctx->cb = cb;
1929 0 : rw_ctx->file_ctx = file_ctx;
1930 :
1931 0 : tev = tevent_add_timer(ev, rw_ctx, tv, rewatch_config_file, rw_ctx);
1932 0 : if (tev == NULL) {
1933 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1934 : "Could not restore inotify watch. Quitting!\n");
1935 0 : close(file_ctx->mt_ctx->inotify_fd);
1936 0 : kill(getpid(), SIGTERM);
1937 : }
1938 0 : goto done;
1939 : }
1940 :
1941 : /* Tell the monitor to signal the children */
1942 0 : cb->fn(file_ctx, cb->filename);
1943 0 : file_ctx->needs_update = 0;
1944 :
1945 : done:
1946 0 : talloc_free(tmp_ctx);
1947 : }
1948 :
1949 0 : static void rewatch_config_file(struct tevent_context *ev,
1950 : struct tevent_timer *te,
1951 : struct timeval t, void *ptr)
1952 : {
1953 : int err;
1954 0 : struct tevent_timer *tev = NULL;
1955 : struct timeval tv;
1956 : struct config_file_callback *cb;
1957 :
1958 : struct rewatch_ctx *rw_ctx;
1959 : struct config_file_ctx *file_ctx;
1960 :
1961 0 : rw_ctx = talloc_get_type(ptr, struct rewatch_ctx);
1962 :
1963 0 : cb = rw_ctx->cb;
1964 0 : file_ctx = rw_ctx->file_ctx;
1965 :
1966 : /* Retry six times at five-second intervals before giving up */
1967 0 : cb->retries++;
1968 0 : if (cb->retries > 6) {
1969 0 : DEBUG(SSSDBG_FATAL_FAILURE,
1970 : "Could not restore inotify watch. Switching to polling!\n");
1971 0 : close(file_ctx->mt_ctx->inotify_fd);
1972 0 : err = monitor_config_file_fallback(file_ctx->parent_ctx,
1973 : file_ctx->mt_ctx,
1974 0 : cb->filename,
1975 : cb->fn,true);
1976 0 : if (err != EOK)
1977 0 : kill(getpid(), SIGTERM);
1978 :
1979 0 : cb->fn(file_ctx, cb->filename);
1980 0 : talloc_free(rw_ctx);
1981 :
1982 : /* A new callback was created in monitor_config_file_fallback()*/
1983 0 : DLIST_REMOVE(file_ctx->callbacks, cb);
1984 0 : talloc_free(cb);
1985 :
1986 0 : return;
1987 : }
1988 :
1989 0 : cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
1990 0 : cb->filename, IN_MODIFY);
1991 0 : if (cb->wd < 0) {
1992 0 : err = errno;
1993 :
1994 0 : tv.tv_sec = t.tv_sec+5;
1995 0 : tv.tv_usec = t.tv_usec;
1996 :
1997 0 : DEBUG(SSSDBG_CRIT_FAILURE,
1998 : "Could not add inotify watch for file [%s]. Error [%d:%s]\n",
1999 : cb->filename, err, strerror(err));
2000 :
2001 0 : tev = tevent_add_timer(ev, ev, tv, rewatch_config_file, rw_ctx);
2002 0 : if (tev == NULL) {
2003 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2004 : "Could not restore inotify watch. Quitting!\n");
2005 0 : close(file_ctx->mt_ctx->inotify_fd);
2006 0 : kill(getpid(), SIGTERM);
2007 : }
2008 :
2009 0 : return;
2010 : }
2011 0 : cb->retries = 0;
2012 :
2013 : /* Tell the monitor to signal the children */
2014 0 : cb->fn(file_ctx, cb->filename);
2015 :
2016 0 : talloc_free(rw_ctx);
2017 0 : file_ctx->needs_update = 0;
2018 : }
2019 : #endif /* HAVE_INOTIFY */
2020 :
2021 0 : static void poll_config_file(struct tevent_context *ev,
2022 : struct tevent_timer *te,
2023 : struct timeval t, void *ptr)
2024 : {
2025 : int ret, err;
2026 : struct stat file_stat;
2027 : struct timeval tv;
2028 : struct config_file_ctx *file_ctx;
2029 : struct config_file_callback *cb;
2030 :
2031 0 : file_ctx = talloc_get_type(ptr,struct config_file_ctx);
2032 :
2033 0 : for (cb = file_ctx->callbacks; cb; cb = cb->next) {
2034 0 : ret = stat(cb->filename, &file_stat);
2035 0 : if (ret < 0) {
2036 0 : err = errno;
2037 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2038 : "Could not stat file [%s]. Error [%d:%s]\n",
2039 : cb->filename, err, strerror(err));
2040 : /* TODO: If the config file is missing, should we shut down? */
2041 0 : return;
2042 : }
2043 :
2044 0 : if (file_stat.st_mtime != cb->modified) {
2045 : /* Parse the configuration file and signal the children */
2046 : /* Note: this will fire if the modification time changes into the past
2047 : * as well as the future.
2048 : */
2049 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Config file changed\n");
2050 0 : cb->modified = file_stat.st_mtime;
2051 :
2052 : /* Tell the monitor to signal the children */
2053 0 : cb->fn(file_ctx, cb->filename);
2054 : }
2055 : }
2056 :
2057 0 : gettimeofday(&tv, NULL);
2058 0 : tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
2059 0 : tv.tv_usec = 0;
2060 0 : file_ctx->timer = tevent_add_timer(ev, file_ctx->parent_ctx, tv,
2061 : poll_config_file, file_ctx);
2062 0 : if (!file_ctx->timer) {
2063 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2064 : "Error: Config file no longer monitored for changes!\n");
2065 : }
2066 : }
2067 :
2068 0 : static int try_inotify(struct config_file_ctx *file_ctx, const char *filename,
2069 : monitor_reconf_fn fn)
2070 : {
2071 : #ifdef HAVE_INOTIFY
2072 : int err, fd_args, ret;
2073 : struct tevent_fd *tfd;
2074 : struct config_file_callback *cb;
2075 :
2076 : /* Monitoring the file descriptor should be global */
2077 0 : if (!file_ctx->mt_ctx->inotify_fd) {
2078 : /* Set up inotify to monitor the config file for changes */
2079 0 : file_ctx->mt_ctx->inotify_fd = inotify_init();
2080 0 : if (file_ctx->mt_ctx->inotify_fd < 0) {
2081 0 : err = errno;
2082 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2083 : "Could not initialize inotify, error [%d:%s]\n",
2084 : err, strerror(err));
2085 0 : return err;
2086 : }
2087 :
2088 0 : fd_args = fcntl(file_ctx->mt_ctx->inotify_fd, F_GETFL, NULL);
2089 0 : if (fd_args < 0) {
2090 : /* Could not set nonblocking */
2091 0 : close(file_ctx->mt_ctx->inotify_fd);
2092 0 : return EINVAL;
2093 : }
2094 :
2095 0 : fd_args |= O_NONBLOCK;
2096 0 : ret = fcntl(file_ctx->mt_ctx->inotify_fd, F_SETFL, fd_args);
2097 0 : if (ret < 0) {
2098 : /* Could not set nonblocking */
2099 0 : close(file_ctx->mt_ctx->inotify_fd);
2100 0 : return EINVAL;
2101 : }
2102 :
2103 : /* Add the inotify file descriptor to the TEvent context */
2104 0 : tfd = tevent_add_fd(file_ctx->mt_ctx->ev, file_ctx,
2105 : file_ctx->mt_ctx->inotify_fd,
2106 : TEVENT_FD_READ, config_file_changed,
2107 : file_ctx);
2108 0 : if (!tfd) {
2109 0 : close(file_ctx->mt_ctx->inotify_fd);
2110 0 : return EIO;
2111 : }
2112 : }
2113 :
2114 0 : cb = talloc_zero(file_ctx, struct config_file_callback);
2115 0 : if(!cb) {
2116 0 : close(file_ctx->mt_ctx->inotify_fd);
2117 0 : return ENOMEM;
2118 : }
2119 :
2120 0 : cb->filename = talloc_strdup(cb, filename);
2121 0 : if (!cb->filename) {
2122 0 : close(file_ctx->mt_ctx->inotify_fd);
2123 0 : return ENOMEM;
2124 : }
2125 0 : cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
2126 0 : cb->filename, IN_MODIFY);
2127 0 : if (cb->wd < 0) {
2128 0 : err = errno;
2129 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2130 : "Could not add inotify watch for file [%s]. Error [%d:%s]\n",
2131 : cb->filename, err, strerror(err));
2132 0 : close(file_ctx->mt_ctx->inotify_fd);
2133 0 : return err;
2134 : }
2135 0 : cb->fn = fn;
2136 :
2137 0 : DLIST_ADD(file_ctx->callbacks, cb);
2138 :
2139 0 : return EOK;
2140 : #else
2141 : return EINVAL;
2142 : #endif /* HAVE_INOTIFY */
2143 : }
2144 :
2145 0 : static int monitor_config_file(TALLOC_CTX *mem_ctx,
2146 : struct mt_ctx *ctx,
2147 : const char *file,
2148 : monitor_reconf_fn fn,
2149 : bool ignore_missing)
2150 : {
2151 : int ret, err;
2152 : bool use_inotify;
2153 : struct stat file_stat;
2154 :
2155 0 : ret = stat(file, &file_stat);
2156 0 : if (ret < 0) {
2157 0 : err = errno;
2158 0 : if (err == ENOENT && ignore_missing) {
2159 0 : DEBUG(SSSDBG_MINOR_FAILURE,
2160 : "file [%s] is missing. Will not update online status "
2161 : "based on watching the file\n", file);
2162 0 : return EOK;
2163 : } else {
2164 0 : DEBUG(SSSDBG_MINOR_FAILURE,
2165 : "Could not stat file [%s]. Error [%d:%s]\n",
2166 : file, err, strerror(err));
2167 :
2168 0 : return err;
2169 : }
2170 : }
2171 0 : if (!ctx->file_ctx) {
2172 0 : ctx->file_ctx = talloc_zero(mem_ctx, struct config_file_ctx);
2173 0 : if (!ctx->file_ctx) return ENOMEM;
2174 :
2175 0 : ctx->file_ctx->parent_ctx = mem_ctx;
2176 0 : ctx->file_ctx->mt_ctx = ctx;
2177 : }
2178 :
2179 0 : ret = confdb_get_bool(ctx->cdb,
2180 : CONFDB_MONITOR_CONF_ENTRY,
2181 : CONFDB_MONITOR_TRY_INOTIFY,
2182 : true, &use_inotify);
2183 0 : if (ret != EOK) {
2184 0 : talloc_free(ctx->file_ctx);
2185 0 : return ret;
2186 : }
2187 :
2188 0 : if (use_inotify) {
2189 0 : ret = try_inotify(ctx->file_ctx, file, fn);
2190 0 : if (ret != EOK) {
2191 0 : use_inotify = false;
2192 : }
2193 : }
2194 :
2195 0 : if (!use_inotify) {
2196 : /* Could not monitor file with inotify, fall back to polling */
2197 0 : ret = monitor_config_file_fallback(mem_ctx, ctx, file, fn, true);
2198 : }
2199 :
2200 0 : return ret;
2201 : }
2202 :
2203 0 : static errno_t monitor_config_file_fallback(TALLOC_CTX *mem_ctx,
2204 : struct mt_ctx *ctx,
2205 : const char *file,
2206 : monitor_reconf_fn fn,
2207 : bool ignore_missing)
2208 : {
2209 0 : struct config_file_callback *cb = NULL;
2210 : struct stat file_stat;
2211 : int ret, err;
2212 : struct timeval tv;
2213 :
2214 0 : ret = stat(file, &file_stat);
2215 0 : if (ret < 0) {
2216 0 : err = errno;
2217 0 : if (err == ENOENT && ignore_missing) {
2218 0 : DEBUG(SSSDBG_MINOR_FAILURE,
2219 : "file [%s] is missing. Will not update online status "
2220 : "based on watching the file\n", file);
2221 0 : return EOK;
2222 :
2223 : } else {
2224 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2225 : "Could not stat file [%s]. Error [%d:%s]\n",
2226 : file, err, strerror(err));
2227 :
2228 0 : return err;
2229 : }
2230 : }
2231 :
2232 0 : cb = talloc_zero(ctx->file_ctx, struct config_file_callback);
2233 0 : if (!cb) {
2234 0 : talloc_free(ctx->file_ctx);
2235 0 : return ENOMEM;
2236 : }
2237 0 : cb->filename = talloc_strdup(cb, file);
2238 0 : if (!cb->filename) {
2239 0 : talloc_free(ctx->file_ctx);
2240 0 : return ENOMEM;
2241 : }
2242 0 : cb->fn = fn;
2243 0 : cb->modified = file_stat.st_mtime;
2244 :
2245 0 : DLIST_ADD(ctx->file_ctx->callbacks, cb);
2246 :
2247 0 : if(!ctx->file_ctx->timer) {
2248 0 : gettimeofday(&tv, NULL);
2249 0 : tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
2250 0 : tv.tv_usec = 0;
2251 0 : ctx->file_ctx->timer = tevent_add_timer(ctx->ev, mem_ctx, tv,
2252 : poll_config_file, ctx->file_ctx);
2253 0 : if (!ctx->file_ctx->timer) {
2254 0 : talloc_free(ctx->file_ctx);
2255 0 : return EIO;
2256 : }
2257 : }
2258 :
2259 0 : return EOK;
2260 : }
2261 :
2262 : #define MISSING_RESOLV_CONF_POLL_TIME 10
2263 :
2264 0 : static void missing_resolv_conf(struct tevent_context *ev,
2265 : struct tevent_timer *te,
2266 : struct timeval tv, void *data)
2267 : {
2268 : int ret;
2269 0 : struct mt_ctx *ctx = talloc_get_type(data, struct mt_ctx);
2270 :
2271 0 : ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
2272 : monitor_update_resolv, false);
2273 0 : if (ret == EOK) {
2274 0 : signal_res_init(ctx);
2275 0 : } else if (ret == ENOENT) {
2276 0 : tv = tevent_timeval_current_ofs(MISSING_RESOLV_CONF_POLL_TIME, 0);
2277 0 : te = tevent_add_timer(ctx->ev, ctx, tv, missing_resolv_conf, ctx);
2278 0 : if (te == NULL) {
2279 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2280 : "tevent_add_timer failed. resolv.conf will be ignored.\n");
2281 : }
2282 : } else {
2283 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2284 : "Monitor_config_file failed. resolv.conf will be ignored.\n");
2285 : }
2286 0 : }
2287 :
2288 0 : static int monitor_process_init(struct mt_ctx *ctx,
2289 : const char *config_file)
2290 : {
2291 : TALLOC_CTX *tmp_ctx;
2292 : struct tevent_signal *tes;
2293 : struct timeval tv;
2294 : struct tevent_timer *te;
2295 : struct sss_domain_info *dom;
2296 : char *rcachedir;
2297 : int num_providers;
2298 : int ret;
2299 : int error;
2300 :
2301 : /* Set up the environment variable for the Kerberos Replay Cache */
2302 0 : ret = confdb_get_string(ctx->cdb, ctx,
2303 : CONFDB_MONITOR_CONF_ENTRY,
2304 : CONFDB_MONITOR_KRB5_RCACHEDIR,
2305 : KRB5_RCACHE_DIR,
2306 : &rcachedir);
2307 0 : if (ret != EOK) {
2308 0 : return ret;
2309 : }
2310 :
2311 0 : if (strcmp(rcachedir, KRB5_RCACHE_DIR_DISABLE) != 0)
2312 : {
2313 0 : errno = 0;
2314 0 : ret = setenv("KRB5RCACHEDIR", rcachedir, 1);
2315 0 : if (ret < 0) {
2316 0 : error = errno;
2317 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2318 : "Unable to set KRB5RCACHEDIR: %s."
2319 : "Will attempt to use libkrb5 defaults\n",
2320 : strerror(error));
2321 : }
2322 0 : talloc_zfree(rcachedir);
2323 : }
2324 :
2325 : /* Set up an event handler for a SIGHUP */
2326 0 : tes = tevent_add_signal(ctx->ev, ctx, SIGHUP, 0,
2327 : monitor_hup, ctx);
2328 0 : if (tes == NULL) {
2329 0 : return EIO;
2330 : }
2331 :
2332 : /* Set up an event handler for a SIGINT */
2333 0 : BlockSignals(false, SIGINT);
2334 0 : tes = tevent_add_signal(ctx->ev, ctx, SIGINT, 0,
2335 : monitor_quit_signal, ctx);
2336 0 : if (tes == NULL) {
2337 0 : return EIO;
2338 : }
2339 :
2340 : /* Set up an event handler for a SIGTERM */
2341 0 : tes = tevent_add_signal(ctx->ev, ctx, SIGTERM, 0,
2342 : monitor_quit_signal, ctx);
2343 0 : if (tes == NULL) {
2344 0 : return EIO;
2345 : }
2346 :
2347 : /* Handle SIGUSR1 (tell all providers to go offline) */
2348 0 : BlockSignals(false, SIGUSR1);
2349 0 : tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
2350 : signal_offline, ctx);
2351 0 : if (tes == NULL) {
2352 0 : return EIO;
2353 : }
2354 :
2355 : /* Handle SIGUSR2 (tell all providers to go reset offline) */
2356 0 : BlockSignals(false, SIGUSR2);
2357 0 : tes = tevent_add_signal(ctx->ev, ctx, SIGUSR2, 0,
2358 : signal_offline_reset, ctx);
2359 0 : if (tes == NULL) {
2360 0 : return EIO;
2361 : }
2362 :
2363 : /* Set up the SIGCHLD handler */
2364 0 : ret = sss_sigchld_init(ctx, ctx->ev, &ctx->sigchld_ctx);
2365 0 : if (ret != EOK) return ret;
2366 :
2367 : #if 0
2368 : This feature is incomplete and can leave the SSSD in a bad state if the
2369 : config file is changed while the SSSD is running.
2370 :
2371 : Uncomment this once the backends are honoring reloadConfig()
2372 :
2373 : /* Watch for changes to the confdb config file */
2374 : ret = monitor_config_file(ctx, ctx, config_file, monitor_signal_reconf,
2375 : true);
2376 : if (ret != EOK) {
2377 : return ret;
2378 : }
2379 : #endif
2380 : /* Watch for changes to the DNS resolv.conf */
2381 0 : ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
2382 : monitor_update_resolv, false);
2383 0 : if (ret == ENOENT) {
2384 0 : tv = tevent_timeval_current_ofs(MISSING_RESOLV_CONF_POLL_TIME, 0);
2385 0 : te = tevent_add_timer(ctx->ev, ctx, tv, missing_resolv_conf, ctx);
2386 0 : if (te == NULL) {
2387 0 : DEBUG(SSSDBG_FATAL_FAILURE, "resolv.conf will be ignored\n");
2388 : }
2389 0 : } else if (ret != EOK) {
2390 0 : return ret;
2391 : }
2392 :
2393 : /* Avoid a startup race condition between process.
2394 : * We need to handle DB upgrades or DB creation only
2395 : * in one process before all other start.
2396 : */
2397 0 : tmp_ctx = talloc_new(NULL);
2398 0 : if (!tmp_ctx) {
2399 0 : return ENOMEM;
2400 : }
2401 0 : ret = sysdb_init_ext(tmp_ctx, ctx->domains, true,
2402 : true, ctx->uid, ctx->gid);
2403 0 : if (ret != EOK) {
2404 0 : SYSDB_VERSION_ERROR_DAEMON(ret);
2405 0 : return ret;
2406 : }
2407 0 : talloc_zfree(tmp_ctx);
2408 :
2409 : /* Initialize D-BUS Server
2410 : * The monitor will act as a D-BUS server for all
2411 : * SSSD processes */
2412 0 : ret = monitor_dbus_init(ctx);
2413 0 : if (ret != EOK) {
2414 0 : return ret;
2415 : }
2416 :
2417 0 : ret = setup_netlink(ctx, ctx->ev, network_status_change_cb,
2418 : ctx, &ctx->nlctx);
2419 0 : if (ret != EOK) {
2420 0 : DEBUG(SSSDBG_OP_FAILURE,
2421 : "Cannot set up listening for network notifications\n");
2422 0 : return ret;
2423 : }
2424 :
2425 : /* start providers */
2426 0 : num_providers = 0;
2427 0 : for (dom = ctx->domains; dom; dom = get_next_domain(dom, false)) {
2428 0 : ret = add_new_provider(ctx, dom->name, 0);
2429 0 : if (ret != EOK && ret != ENOENT) {
2430 0 : return ret;
2431 : }
2432 0 : if (ret != ENOENT) {
2433 0 : num_providers++;
2434 : }
2435 : }
2436 :
2437 0 : if (num_providers > 0) {
2438 : /* now set the services stratup timeout *
2439 : * (responders will be started automatically when all
2440 : * providers are up and running or when the tomeout
2441 : * expires) */
2442 0 : ret = add_services_startup_timeout(ctx);
2443 0 : if (ret != EOK) {
2444 0 : return ret;
2445 : }
2446 : } else {
2447 : int i;
2448 :
2449 0 : ctx->services_started = true;
2450 :
2451 : /* No providers start services immediately
2452 : * Normally this means only LOCAL is configured */
2453 0 : for (i = 0; ctx->services[i]; i++) {
2454 0 : add_new_service(ctx, ctx->services[i], 0);
2455 : }
2456 : }
2457 :
2458 0 : return EOK;
2459 : }
2460 :
2461 0 : static void init_timeout(struct tevent_context *ev,
2462 : struct tevent_timer *te,
2463 : struct timeval t, void *ptr)
2464 : {
2465 : struct mon_init_conn *mini;
2466 :
2467 0 : DEBUG(SSSDBG_OP_FAILURE, "Client timed out before Identification!\n");
2468 :
2469 0 : mini = talloc_get_type(ptr, struct mon_init_conn);
2470 :
2471 0 : sbus_disconnect(mini->conn);
2472 0 : talloc_zfree(mini);
2473 0 : }
2474 :
2475 : /*
2476 : * monitor_service_init
2477 : * Set up a timeout function and temporary connection structure.
2478 : * If the client does not identify before the timeout kicks in,
2479 : * the client is forcibly disconnected.
2480 : */
2481 0 : static int monitor_service_init(struct sbus_connection *conn, void *data)
2482 : {
2483 : struct mt_ctx *ctx;
2484 : struct mon_init_conn *mini;
2485 : struct timeval tv;
2486 :
2487 0 : DEBUG(SSSDBG_TRACE_FUNC, "Initializing D-BUS Service\n");
2488 :
2489 0 : ctx = talloc_get_type(data, struct mt_ctx);
2490 :
2491 0 : mini = talloc(conn, struct mon_init_conn);
2492 0 : if (!mini) {
2493 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
2494 0 : talloc_zfree(conn);
2495 0 : return ENOMEM;
2496 : }
2497 0 : mini->ctx = ctx;
2498 0 : mini->conn = conn;
2499 :
2500 : /* Allow access from the SSSD user */
2501 0 : sbus_allow_uid(conn, &ctx->uid);
2502 :
2503 : /* 10 seconds should be plenty */
2504 0 : tv = tevent_timeval_current_ofs(10, 0);
2505 :
2506 0 : mini->timeout = tevent_add_timer(ctx->ev, mini, tv, init_timeout, mini);
2507 0 : if (!mini->timeout) {
2508 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
2509 0 : talloc_zfree(conn);
2510 0 : return ENOMEM;
2511 : }
2512 :
2513 0 : return sbus_conn_register_iface(conn, &monitor_methods.vtable,
2514 : MON_SRV_PATH, mini);
2515 : }
2516 :
2517 : /* service_send_ping
2518 : * this function send a dbus ping to a service.
2519 : * It returns EOK if all is fine or ENXIO if the connection is
2520 : * not available (either not yet set up or teared down).
2521 : * Returns e generic error in other cases.
2522 : */
2523 0 : static int service_send_ping(struct mt_svc *svc)
2524 : {
2525 : DBusMessage *msg;
2526 : int ret;
2527 :
2528 0 : if (!svc->conn) {
2529 0 : DEBUG(SSSDBG_TRACE_INTERNAL, "Service not yet initialized\n");
2530 0 : return ENXIO;
2531 : }
2532 :
2533 0 : DEBUG(SSSDBG_CONF_SETTINGS,"Pinging %s\n", svc->name);
2534 :
2535 : /*
2536 : * Set up identity request
2537 : * This should be a well-known path and method
2538 : * for all services
2539 : */
2540 0 : msg = dbus_message_new_method_call(NULL,
2541 : MONITOR_PATH,
2542 : MON_CLI_IFACE,
2543 : MON_CLI_IFACE_PING);
2544 0 : if (!msg) {
2545 0 : DEBUG(SSSDBG_FATAL_FAILURE,"Out of memory?!\n");
2546 0 : talloc_zfree(svc->conn);
2547 0 : return ENOMEM;
2548 : }
2549 :
2550 0 : ret = sbus_conn_send(svc->conn, msg,
2551 0 : svc->ping_time * 1000, /* milliseconds */
2552 : ping_check, svc, &svc->pending);
2553 0 : dbus_message_unref(msg);
2554 0 : return ret;
2555 : }
2556 :
2557 0 : static void ping_check(DBusPendingCall *pending, void *data)
2558 : {
2559 : struct mt_svc *svc;
2560 : DBusMessage *reply;
2561 : const char *dbus_error_name;
2562 : size_t len;
2563 : int type;
2564 :
2565 0 : svc = talloc_get_type(data, struct mt_svc);
2566 0 : if (!svc) {
2567 : /* The connection probably went down before the callback fired.
2568 : * Not much we can do. */
2569 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Invalid service pointer.\n");
2570 0 : return;
2571 : }
2572 0 : svc->pending = NULL;
2573 :
2574 0 : reply = dbus_pending_call_steal_reply(pending);
2575 0 : if (!reply) {
2576 : /* reply should never be null. This function shouldn't be called
2577 : * until reply is valid or timeout has occurred. If reply is NULL
2578 : * here, something is seriously wrong and we should bail out.
2579 : */
2580 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2581 : "A reply callback was called but no reply was received"
2582 : " and no timeout occurred\n");
2583 :
2584 : /* Destroy this connection */
2585 0 : sbus_disconnect(svc->conn);
2586 0 : goto done;
2587 : }
2588 :
2589 0 : type = dbus_message_get_type(reply);
2590 0 : switch (type) {
2591 : case DBUS_MESSAGE_TYPE_METHOD_RETURN:
2592 : /* ok peer replied,
2593 : * make sure we reset the failure counter in the service structure */
2594 :
2595 0 : DEBUG(SSSDBG_CONF_SETTINGS,"Service %s replied to ping\n", svc->name);
2596 :
2597 0 : svc->failed_pongs = 0;
2598 0 : break;
2599 :
2600 : case DBUS_MESSAGE_TYPE_ERROR:
2601 :
2602 0 : dbus_error_name = dbus_message_get_error_name(reply);
2603 0 : if (!dbus_error_name) {
2604 0 : dbus_error_name = "<UNKNOWN>";
2605 : }
2606 :
2607 0 : len = strlen(DBUS_ERROR_NO_REPLY);
2608 :
2609 : /* Increase failed pong count */
2610 0 : if (strnlen(dbus_error_name, len + 1) == len
2611 0 : && strncmp(dbus_error_name, DBUS_ERROR_NO_REPLY, len) == 0) {
2612 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2613 : "A service PING timed out on [%s]. "
2614 : "Attempt [%d]\n",
2615 : svc->name, svc->failed_pongs);
2616 0 : svc->failed_pongs++;
2617 0 : break;
2618 : }
2619 :
2620 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2621 : "A service PING returned an error [%s], closing connection.\n",
2622 : dbus_error_name);
2623 : /* Falling through to default intentionally*/
2624 : default:
2625 : /*
2626 : * Timeout or other error occurred or something
2627 : * unexpected happened.
2628 : * It doesn't matter which, because either way we
2629 : * know that this connection isn't trustworthy.
2630 : * We'll destroy it now.
2631 : */
2632 0 : sbus_disconnect(svc->conn);
2633 : }
2634 :
2635 : done:
2636 0 : dbus_pending_call_unref(pending);
2637 0 : dbus_message_unref(reply);
2638 : }
2639 :
2640 : static void service_startup_handler(struct tevent_context *ev,
2641 : struct tevent_timer *te,
2642 : struct timeval t, void *ptr);
2643 :
2644 0 : static int start_service(struct mt_svc *svc)
2645 : {
2646 : struct tevent_timer *te;
2647 : struct timeval tv;
2648 :
2649 0 : DEBUG(SSSDBG_CONF_SETTINGS,"Queueing service %s for startup\n", svc->name);
2650 :
2651 0 : tv = tevent_timeval_current();
2652 :
2653 : /* Add a timed event to start up the service.
2654 : * We have to do this in order to avoid a race
2655 : * condition where the service being started forks
2656 : * and attempts to connect to the SBUS before
2657 : * the monitor is serving it.
2658 : */
2659 0 : te = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
2660 : service_startup_handler, svc);
2661 0 : if (te == NULL) {
2662 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2663 : "Unable to queue service %s for startup\n", svc->name);
2664 0 : return ENOMEM;
2665 : }
2666 0 : return EOK;
2667 : }
2668 :
2669 : static void mt_svc_exit_handler(int pid, int wait_status, void *pvt);
2670 0 : static void service_startup_handler(struct tevent_context *ev,
2671 : struct tevent_timer *te,
2672 : struct timeval t, void *ptr)
2673 : {
2674 : errno_t ret;
2675 : struct mt_svc *mt_svc;
2676 : char **args;
2677 :
2678 0 : mt_svc = talloc_get_type(ptr, struct mt_svc);
2679 0 : if (mt_svc == NULL) {
2680 0 : return;
2681 : }
2682 :
2683 0 : mt_svc->pid = fork();
2684 0 : if (mt_svc->pid != 0) {
2685 0 : if (mt_svc->pid == -1) {
2686 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2687 : "Could not fork child to start service [%s]. "
2688 : "Continuing.\n", mt_svc->name);
2689 0 : return;
2690 : }
2691 :
2692 : /* Parent */
2693 0 : mt_svc->mt_ctx->check_children = true;
2694 0 : mt_svc->failed_pongs = 0;
2695 :
2696 : /* Handle process exit */
2697 0 : ret = sss_child_register(mt_svc,
2698 0 : mt_svc->mt_ctx->sigchld_ctx,
2699 : mt_svc->pid,
2700 : mt_svc_exit_handler,
2701 : mt_svc,
2702 : &mt_svc->child_ctx);
2703 0 : if (ret != EOK) {
2704 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2705 : "Could not register sigchld handler.\n");
2706 : /* Should we exit here? For now, we'll hope this
2707 : * child never dies, because we can't restart it.
2708 : */
2709 : }
2710 :
2711 0 : DLIST_ADD(mt_svc->mt_ctx->svc_list, mt_svc);
2712 0 : set_tasks_checker(mt_svc);
2713 :
2714 0 : return;
2715 : }
2716 :
2717 : /* child */
2718 :
2719 0 : args = parse_args(mt_svc->command);
2720 0 : execvp(args[0], args);
2721 :
2722 : /* If we are here, exec() has failed
2723 : * Print errno and abort quickly */
2724 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2725 : "Could not exec %s, reason: %s\n", mt_svc->command, strerror(errno));
2726 :
2727 : /* We have to call _exit() instead of exit() here
2728 : * because a bug in D-BUS will cause the server to
2729 : * close its socket at exit() */
2730 0 : _exit(1);
2731 : }
2732 :
2733 0 : static void mt_svc_restart(struct tevent_context *ev,
2734 : struct tevent_timer *te,
2735 : struct timeval t, void *ptr)
2736 : {
2737 : struct mt_svc *svc;
2738 :
2739 0 : svc = talloc_get_type(ptr, struct mt_svc);
2740 0 : if (svc == NULL) {
2741 0 : return;
2742 : }
2743 :
2744 0 : DEBUG(SSSDBG_TRACE_FUNC, "Scheduling service %s for restart %d\n",
2745 : svc->name, svc->restarts+1);
2746 :
2747 0 : if (svc->type == MT_SVC_SERVICE) {
2748 0 : add_new_service(svc->mt_ctx, svc->name, svc->restarts + 1);
2749 0 : } else if (svc->type == MT_SVC_PROVIDER) {
2750 0 : add_new_provider(svc->mt_ctx, svc->name, svc->restarts + 1);
2751 : } else {
2752 : /* Invalid type? */
2753 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2754 : "BUG: Invalid child process type [%d]\n", svc->type);
2755 : }
2756 :
2757 : /* Free the old service (which will also remove it
2758 : * from the child list)
2759 : */
2760 0 : talloc_free(svc);
2761 : }
2762 :
2763 0 : static void mt_svc_exit_handler(int pid, int wait_status, void *pvt)
2764 : {
2765 0 : struct mt_svc *svc = talloc_get_type(pvt, struct mt_svc);
2766 :
2767 :
2768 0 : if (WIFEXITED(wait_status)) {
2769 0 : DEBUG(SSSDBG_OP_FAILURE,
2770 : "Child [%s] exited with code [%d]\n",
2771 : svc->name, WEXITSTATUS(wait_status));
2772 0 : } else if (WIFSIGNALED(wait_status)) {
2773 0 : DEBUG(SSSDBG_OP_FAILURE,
2774 : "Child [%s] terminated with signal [%d]\n",
2775 : svc->name, WTERMSIG(wait_status));
2776 : } else {
2777 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2778 : "Child [%s] did not exit cleanly\n", svc->name);
2779 : /* Forcibly kill this child, just in case */
2780 0 : kill(svc->pid, SIGKILL);
2781 :
2782 : /* Return and let us get caught by another
2783 : * call to the SIGCHLD handler
2784 : */
2785 0 : return;
2786 : }
2787 :
2788 : /* Clear the kill_timer so we don't try to SIGKILL it after it's
2789 : * already gone.
2790 : */
2791 0 : talloc_zfree(svc->kill_timer);
2792 :
2793 : /* Check the number of restart tries and relaunch the service */
2794 0 : monitor_restart_service(svc);
2795 :
2796 0 : return;
2797 : }
2798 :
2799 0 : static void monitor_restart_service(struct mt_svc *svc)
2800 : {
2801 0 : struct mt_ctx *mt_ctx = svc->mt_ctx;
2802 : int restart_delay;
2803 0 : time_t now = time(NULL);
2804 : struct tevent_timer *te;
2805 : struct timeval tv;
2806 :
2807 : /* Handle the actual checks for how many times to restart this
2808 : * service before giving up.
2809 : */
2810 0 : if ((now - svc->last_restart) > MONITOR_RESTART_CNT_INTERVAL_RESET) {
2811 0 : svc->restarts = 0;
2812 : }
2813 :
2814 : /* Restart the service */
2815 0 : if (svc->restarts > MONITOR_MAX_SVC_RESTARTS) {
2816 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2817 : "Process [%s], definitely stopped!\n", svc->name);
2818 :
2819 0 : sss_log(SSS_LOG_ERR,
2820 : "Exiting the SSSD. Could not restart critical service [%s].",
2821 : svc->name);
2822 :
2823 0 : talloc_free(svc);
2824 :
2825 : /* exit the SSSD with an error, shutting down all
2826 : * services and domains.
2827 : * We do this because if one of the responders is down
2828 : * and can't come back up, this is the only way to
2829 : * guarantee admin intervention.
2830 : */
2831 0 : monitor_quit(mt_ctx, 1);
2832 0 : return;
2833 : }
2834 :
2835 : /* restarts are schedule after 0, 2, 4 seconds */
2836 0 : restart_delay = svc->restarts << 1;
2837 0 : if (restart_delay > MONITOR_MAX_RESTART_DELAY) {
2838 0 : restart_delay = MONITOR_MAX_RESTART_DELAY;
2839 : }
2840 :
2841 0 : tv = tevent_timeval_current_ofs(restart_delay, 0);
2842 0 : te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, mt_svc_restart, svc);
2843 0 : if (te == NULL) {
2844 : /* Nothing much we can do */
2845 0 : DEBUG(SSSDBG_CRIT_FAILURE,
2846 : "Failed to allocate timed event: mt_svc_restart.\n");
2847 0 : talloc_free(svc);
2848 0 : return;
2849 : }
2850 : }
2851 :
2852 0 : int main(int argc, const char *argv[])
2853 : {
2854 : int opt;
2855 : poptContext pc;
2856 0 : int opt_daemon = 0;
2857 0 : int opt_interactive = 0;
2858 0 : int opt_version = 0;
2859 0 : char *opt_config_file = NULL;
2860 0 : char *config_file = NULL;
2861 0 : int flags = 0;
2862 : struct main_context *main_ctx;
2863 : TALLOC_CTX *tmp_ctx;
2864 : struct mt_ctx *monitor;
2865 : int ret;
2866 : uid_t uid;
2867 :
2868 0 : struct poptOption long_options[] = {
2869 : POPT_AUTOHELP
2870 0 : SSSD_MAIN_OPTS
2871 : {"daemon", 'D', POPT_ARG_NONE, &opt_daemon, 0, \
2872 0 : _("Become a daemon (default)"), NULL }, \
2873 : {"interactive", 'i', POPT_ARG_NONE, &opt_interactive, 0, \
2874 0 : _("Run interactive (not a daemon)"), NULL}, \
2875 : {"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \
2876 0 : _("Specify a non-default config file"), NULL}, \
2877 : {"version", '\0', POPT_ARG_NONE, &opt_version, 0, \
2878 0 : _("Print version number and exit"), NULL }, \
2879 : POPT_TABLEEND
2880 : };
2881 :
2882 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
2883 0 : debug_level = SSSDBG_INVALID;
2884 :
2885 0 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
2886 0 : while((opt = poptGetNextOpt(pc)) != -1) {
2887 : switch(opt) {
2888 : default:
2889 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
2890 : poptBadOption(pc, 0), poptStrerror(opt));
2891 0 : poptPrintUsage(pc, stderr, 0);
2892 0 : return 1;
2893 : }
2894 : }
2895 :
2896 0 : DEBUG_INIT(debug_level);
2897 :
2898 0 : if (opt_version) {
2899 0 : puts(VERSION""PRERELEASE_VERSION);
2900 0 : return EXIT_SUCCESS;
2901 : }
2902 :
2903 : /* If the level or timestamps was passed at the command-line, we want
2904 : * to save it and pass it to the children later.
2905 : */
2906 0 : cmdline_debug_level = debug_level;
2907 0 : cmdline_debug_timestamps = debug_timestamps;
2908 0 : cmdline_debug_microseconds = debug_microseconds;
2909 :
2910 0 : if (opt_daemon && opt_interactive) {
2911 0 : fprintf(stderr, "Option -i|--interactive is not allowed together with -D|--daemon\n");
2912 0 : poptPrintUsage(pc, stderr, 0);
2913 0 : return 1;
2914 : }
2915 :
2916 0 : if (!opt_daemon && !opt_interactive) {
2917 0 : opt_daemon = 1;
2918 : }
2919 :
2920 0 : poptFreeContext(pc);
2921 :
2922 0 : uid = getuid();
2923 0 : if (uid != 0) {
2924 0 : DEBUG(SSSDBG_FATAL_FAILURE,
2925 : "Running under %"SPRIuid", must be root\n", uid);
2926 0 : sss_log(SSS_LOG_ALERT, "sssd must be run as root");
2927 0 : return 8;
2928 : }
2929 :
2930 0 : tmp_ctx = talloc_new(NULL);
2931 0 : if (!tmp_ctx) {
2932 0 : return 7;
2933 : }
2934 :
2935 0 : if (opt_daemon) flags |= FLAGS_DAEMON;
2936 0 : if (opt_interactive) {
2937 0 : flags |= FLAGS_INTERACTIVE;
2938 0 : debug_to_stderr = 1;
2939 : }
2940 :
2941 0 : if (opt_config_file) {
2942 0 : config_file = talloc_strdup(tmp_ctx, opt_config_file);
2943 : } else {
2944 0 : config_file = talloc_strdup(tmp_ctx, CONFDB_DEFAULT_CONFIG_FILE);
2945 : }
2946 :
2947 0 : if (!config_file) {
2948 0 : return 6;
2949 : }
2950 :
2951 : /* we want a pid file check */
2952 0 : flags |= FLAGS_PID_FILE;
2953 :
2954 : /* Open before server_setup() does to have logging
2955 : * during configuration checking */
2956 0 : if (debug_to_file) {
2957 0 : ret = open_debug_file();
2958 0 : if (ret) {
2959 0 : return 7;
2960 : }
2961 : }
2962 :
2963 : #ifdef USE_KEYRING
2964 : /* Do this before all the forks, it sets the session key ring so all
2965 : * keys are private to the daemon and cannot be read by any other process
2966 : * tree */
2967 :
2968 : /* make a new session */
2969 0 : ret = keyctl_join_session_keyring(NULL);
2970 0 : if (ret == -1) {
2971 0 : sss_log(SSS_LOG_ALERT,
2972 : "Could not create private keyring session. "
2973 : "If you store password there they may be easily accessible "
2974 0 : "to the root user. (%d, %s)", errno, strerror(errno));
2975 : }
2976 :
2977 0 : ret = keyctl_setperm(KEY_SPEC_SESSION_KEYRING, KEY_POS_ALL);
2978 0 : if (ret == -1) {
2979 0 : sss_log(SSS_LOG_ALERT,
2980 : "Could not set permissions on private keyring. "
2981 : "If you store password there they may be easily accessible "
2982 0 : "to the root user. (%d, %s)", errno, strerror(errno));
2983 : }
2984 : #endif
2985 :
2986 : /* Warn if nscd seems to be running */
2987 0 : ret = check_file(NSCD_SOCKET_PATH,
2988 : -1, -1, S_IFSOCK, S_IFMT, NULL, false);
2989 0 : if (ret == EOK) {
2990 0 : ret = sss_nscd_parse_conf(NSCD_CONF_PATH);
2991 :
2992 0 : switch (ret) {
2993 : case ENOENT:
2994 0 : sss_log(SSS_LOG_NOTICE,
2995 : "NSCD socket was detected. NSCD caching capabilities "
2996 : "may conflict with SSSD for users and groups. It is "
2997 : "recommended not to run NSCD in parallel with SSSD, "
2998 : "unless NSCD is configured not to cache the passwd, "
2999 : "group, netgroup and services nsswitch maps.");
3000 0 : break;
3001 :
3002 : case EEXIST:
3003 0 : sss_log(SSS_LOG_NOTICE,
3004 : "NSCD socket was detected and seems to be configured "
3005 : "to cache some of the databases controlled by "
3006 : "SSSD [passwd,group,netgroup,services]. It is "
3007 : "recommended not to run NSCD in parallel with SSSD, "
3008 : "unless NSCD is configured not to cache these.");
3009 0 : break;
3010 :
3011 : case EOK:
3012 0 : DEBUG(SSSDBG_TRACE_FUNC, "NSCD socket was detected and it "
3013 : "seems to be configured not to interfere with "
3014 : "SSSD's caching capabilities\n");
3015 : }
3016 : }
3017 :
3018 : /* Parse config file, fail if cannot be done */
3019 0 : ret = load_configuration(tmp_ctx, config_file, &monitor);
3020 0 : if (ret != EOK) {
3021 0 : switch (ret) {
3022 : case ERR_MISSING_CONF:
3023 0 : DEBUG(SSSDBG_CRIT_FAILURE,
3024 : "Configuration file: %s does not exist.\n", config_file);
3025 0 : sss_log(SSS_LOG_ALERT,
3026 : "Configuration file: %s does not exist.\n", config_file);
3027 0 : break;
3028 : case EPERM:
3029 : case EACCES:
3030 0 : DEBUG(SSSDBG_CRIT_FAILURE,
3031 : CONF_FILE_PERM_ERROR_MSG, config_file);
3032 0 : sss_log(SSS_LOG_ALERT, CONF_FILE_PERM_ERROR_MSG, config_file);
3033 0 : break;
3034 : default:
3035 0 : DEBUG(SSSDBG_CRIT_FAILURE,
3036 : "SSSD couldn't load the configuration database.\n");
3037 0 : sss_log(SSS_LOG_ALERT,
3038 : "SSSD couldn't load the configuration database [%d]: %s.\n",
3039 : ret, strerror(ret));
3040 0 : break;
3041 : }
3042 0 : return 4;
3043 : }
3044 :
3045 : /* set up things like debug , signals, daemonization, etc... */
3046 0 : monitor->conf_path = CONFDB_MONITOR_CONF_ENTRY;
3047 0 : ret = close(STDIN_FILENO);
3048 0 : if (ret != EOK) return 6;
3049 :
3050 0 : ret = server_setup(MONITOR_NAME, flags, 0, 0,
3051 0 : monitor->conf_path, &main_ctx);
3052 0 : if (ret != EOK) return 2;
3053 :
3054 0 : monitor->is_daemon = !opt_interactive;
3055 0 : monitor->parent_pid = main_ctx->parent_pid;
3056 0 : monitor->ev = main_ctx->event_ctx;
3057 0 : talloc_steal(main_ctx, monitor);
3058 :
3059 0 : ret = monitor_process_init(monitor,
3060 : config_file);
3061 0 : if (ret != EOK) return 3;
3062 0 : talloc_free(tmp_ctx);
3063 :
3064 : /* loop on main */
3065 0 : server_loop(main_ctx);
3066 :
3067 0 : ret = monitor_cleanup();
3068 0 : if (ret != EOK) return 5;
3069 :
3070 0 : return 0;
3071 : }
|