~ubuntu-branches/ubuntu/saucy/sssd/saucy

« back to all changes in this revision

Viewing changes to src/monitor/monitor.c

  • Committer: Stéphane Graber
  • Date: 2011-06-15 16:23:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: stgraber@ubuntu.com-20110615162314-rbhoppnpaxfqo5q7
Merge 1.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#define _GNU_SOURCE
 
23
#include <sys/types.h>
 
24
#include <sys/wait.h>
 
25
#include <sys/time.h>
 
26
#include <sys/param.h>
 
27
#include <time.h>
 
28
#include <string.h>
 
29
#include "config.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
 
 
38
/* Needed for res_init() */
 
39
#include <netinet/in.h>
 
40
#include <arpa/nameser.h>
 
41
#include <resolv.h>
 
42
 
 
43
#include "util/util.h"
 
44
#include "popt.h"
 
45
#include "tevent.h"
 
46
#include "confdb/confdb.h"
 
47
#include "confdb/confdb_setup.h"
 
48
#include "collection.h"
 
49
#include "ini_config.h"
 
50
#include "db/sysdb.h"
 
51
#include "monitor/monitor.h"
 
52
#include "dbus/dbus.h"
 
53
#include "sbus/sssd_dbus.h"
 
54
#include "monitor/monitor_interfaces.h"
 
55
 
 
56
/* ping time cannot be less then once every few seconds or the
 
57
 * monitor will get crazy hammering children with messages */
 
58
#define MONITOR_DEF_PING_TIME 10
 
59
 
 
60
struct svc_spy;
 
61
 
 
62
struct mt_svc {
 
63
    struct mt_svc *prev;
 
64
    struct mt_svc *next;
 
65
    struct sbus_connection *conn;
 
66
    struct svc_spy *conn_spy;
 
67
 
 
68
    struct mt_ctx *mt_ctx;
 
69
 
 
70
    char *provider;
 
71
    char *command;
 
72
    char *name;
 
73
    char *identity;
 
74
    pid_t pid;
 
75
 
 
76
    int ping_time;
 
77
 
 
78
    bool svc_started;
 
79
 
 
80
    int restarts;
 
81
    time_t last_restart;
 
82
    time_t last_ping;
 
83
    int failed_pongs;
 
84
 
 
85
    int debug_level;
 
86
 
 
87
    struct tevent_timer *ping_ev;
 
88
};
 
89
 
 
90
struct config_file_callback {
 
91
    int wd;
 
92
    int retries;
 
93
    monitor_reconf_fn fn;
 
94
    char *filename;
 
95
    time_t modified;
 
96
    struct config_file_callback *next;
 
97
    struct config_file_callback *prev;
 
98
};
 
99
 
 
100
struct config_file_ctx {
 
101
    TALLOC_CTX *parent_ctx;
 
102
    struct tevent_timer *timer;
 
103
    bool needs_update;
 
104
    struct mt_ctx *mt_ctx;
 
105
    struct config_file_callback *callbacks;
 
106
};
 
107
 
 
108
struct mt_ctx {
 
109
    struct tevent_context *ev;
 
110
    struct confdb_ctx *cdb;
 
111
    TALLOC_CTX *domain_ctx; /* Memory context for domain list */
 
112
    struct sss_domain_info *domains;
 
113
    TALLOC_CTX *service_ctx; /* Memory context for services */
 
114
    char **services;
 
115
    struct mt_svc *svc_list;
 
116
    struct sbus_connection *sbus_srv;
 
117
    struct config_file_ctx *file_ctx;
 
118
    int inotify_fd;
 
119
    int service_id_timeout;
 
120
    bool check_children;
 
121
    bool services_started;
 
122
    struct netlink_ctx *nlctx;
 
123
};
 
124
 
 
125
static int start_service(struct mt_svc *mt_svc);
 
126
 
 
127
static int monitor_service_init(struct sbus_connection *conn, void *data);
 
128
 
 
129
static int service_send_ping(struct mt_svc *svc);
 
130
static int service_signal_reset_offline(struct mt_svc *svc);
 
131
static void ping_check(DBusPendingCall *pending, void *data);
 
132
 
 
133
static int service_check_alive(struct mt_svc *svc);
 
134
 
 
135
static void set_tasks_checker(struct mt_svc *srv);
 
136
static void set_global_checker(struct mt_ctx *ctx);
 
137
static int monitor_kill_service (struct mt_svc *svc);
 
138
 
 
139
static int get_service_config(struct mt_ctx *ctx, const char *name,
 
140
                              struct mt_svc **svc_cfg);
 
141
static int get_provider_config(struct mt_ctx *ctx, const char *name,
 
142
                              struct mt_svc **svc_cfg);
 
143
static int add_new_service(struct mt_ctx *ctx, const char *name);
 
144
static int add_new_provider(struct mt_ctx *ctx, const char *name);
 
145
 
 
146
static int mark_service_as_started(struct mt_svc *svc);
 
147
 
 
148
static int monitor_cleanup(void);
 
149
 
 
150
static void network_status_change_cb(enum network_change state,
 
151
                                     void *cb_data)
 
152
{
 
153
    struct mt_svc *iter;
 
154
    struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
 
155
 
 
156
    if (state != NL_ROUTE_UP) return;
 
157
 
 
158
    DEBUG(9, ("A new route has appeared, signaling providers to reset offline status\n"));
 
159
    for (iter = ctx->svc_list; iter; iter = iter->next) {
 
160
        /* Don't signal services, only providers */
 
161
        if (iter->provider) {
 
162
            service_signal_reset_offline(iter);
 
163
        }
 
164
    }
 
165
}
 
166
 
 
167
/* dbus_get_monitor_version
 
168
 * Return the monitor version over D-BUS */
 
169
static int get_monitor_version(DBusMessage *message,
 
170
                               struct sbus_connection *conn)
 
171
{
 
172
    dbus_uint16_t version = MONITOR_VERSION;
 
173
    DBusMessage *reply;
 
174
    dbus_bool_t ret;
 
175
 
 
176
    reply = dbus_message_new_method_return(message);
 
177
    if (!reply) return ENOMEM;
 
178
    ret = dbus_message_append_args(reply,
 
179
                                   DBUS_TYPE_UINT16, &version,
 
180
                                   DBUS_TYPE_INVALID);
 
181
    if (!ret) {
 
182
        dbus_message_unref(reply);
 
183
        return EIO;
 
184
    }
 
185
 
 
186
    /* send reply back */
 
187
    sbus_conn_send_reply(conn, reply);
 
188
    dbus_message_unref(reply);
 
189
 
 
190
    return EOK;
 
191
}
 
192
 
 
193
struct mon_init_conn {
 
194
    struct mt_ctx *ctx;
 
195
    struct sbus_connection *conn;
 
196
    struct tevent_timer *timeout;
 
197
};
 
198
 
 
199
static int add_svc_conn_spy(struct mt_svc *svc);
 
200
 
 
201
/* registers a new client.
 
202
 * if operation is successful also sends back the Monitor version */
 
203
static int client_registration(DBusMessage *message,
 
204
                               struct sbus_connection *conn)
 
205
{
 
206
    dbus_uint16_t version = MONITOR_VERSION;
 
207
    struct mon_init_conn *mini;
 
208
    struct mt_svc *svc;
 
209
    void *data;
 
210
    DBusMessage *reply;
 
211
    DBusError dbus_error;
 
212
    dbus_uint16_t svc_ver;
 
213
    char *svc_name;
 
214
    dbus_bool_t dbret;
 
215
    int ret;
 
216
 
 
217
    data = sbus_conn_get_private_data(conn);
 
218
    mini = talloc_get_type(data, struct mon_init_conn);
 
219
    if (!mini) {
 
220
        DEBUG(0, ("Connection holds no valid init data\n"));
 
221
        return EINVAL;
 
222
    }
 
223
 
 
224
    /* First thing, cancel the timeout */
 
225
    talloc_zfree(mini->timeout);
 
226
 
 
227
    dbus_error_init(&dbus_error);
 
228
 
 
229
    dbret = dbus_message_get_args(message, &dbus_error,
 
230
                                  DBUS_TYPE_STRING, &svc_name,
 
231
                                  DBUS_TYPE_UINT16, &svc_ver,
 
232
                                  DBUS_TYPE_INVALID);
 
233
    if (!dbret) {
 
234
        DEBUG(1, ("Failed to parse message, killing connection\n"));
 
235
        if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
 
236
        sbus_disconnect(conn);
 
237
        /* FIXME: should we just talloc_zfree(conn) ? */
 
238
        goto done;
 
239
    }
 
240
 
 
241
    DEBUG(4, ("Received ID registration: (%s,%d)\n", svc_name, svc_ver));
 
242
 
 
243
    /* search this service in the list */
 
244
    svc = mini->ctx->svc_list;
 
245
    while (svc) {
 
246
        ret = strcasecmp(svc->identity, svc_name);
 
247
        if (ret == 0) {
 
248
            break;
 
249
        }
 
250
        svc = svc->next;
 
251
    }
 
252
    if (!svc) {
 
253
        DEBUG(0, ("Unable to find peer [%s] in list of services,"
 
254
                  " killing connection!\n", svc_name));
 
255
        sbus_disconnect(conn);
 
256
        /* FIXME: should we just talloc_zfree(conn) ? */
 
257
        goto done;
 
258
    }
 
259
 
 
260
    /* Fill in svc structure with connection data */
 
261
    svc->conn = mini->conn;
 
262
 
 
263
    ret = mark_service_as_started(svc);
 
264
    if (ret) {
 
265
        DEBUG(1, ("Failed to mark service [%s]!\n", svc_name));
 
266
        goto done;
 
267
    }
 
268
 
 
269
    /* reply that all is ok */
 
270
    reply = dbus_message_new_method_return(message);
 
271
    if (!reply) return ENOMEM;
 
272
 
 
273
    dbret = dbus_message_append_args(reply,
 
274
                                     DBUS_TYPE_UINT16, &version,
 
275
                                     DBUS_TYPE_INVALID);
 
276
    if (!dbret) {
 
277
        dbus_message_unref(reply);
 
278
        return EIO;
 
279
    }
 
280
 
 
281
    /* send reply back */
 
282
    sbus_conn_send_reply(conn, reply);
 
283
    dbus_message_unref(reply);
 
284
 
 
285
done:
 
286
    /* init complete, get rid of temp init context */
 
287
    talloc_zfree(mini);
 
288
 
 
289
    return EOK;
 
290
}
 
291
 
 
292
struct svc_spy {
 
293
    struct mt_svc *svc;
 
294
};
 
295
 
 
296
static int svc_destructor(void *mem)
 
297
{
 
298
    struct mt_svc *svc = talloc_get_type(mem, struct mt_svc);
 
299
    if (!svc) {
 
300
        /* ?!?!? */
 
301
        return 0;
 
302
    }
 
303
 
 
304
    /* try to delist service */
 
305
    if (svc->mt_ctx) {
 
306
        DLIST_REMOVE(svc->mt_ctx->svc_list, svc);
 
307
    }
 
308
 
 
309
    /* svc is beeing freed, neutralize the spy */
 
310
    if (svc->conn_spy) {
 
311
        talloc_set_destructor((TALLOC_CTX *)svc->conn_spy, NULL);
 
312
        talloc_zfree(svc->conn_spy);
 
313
    }
 
314
    return 0;
 
315
}
 
316
 
 
317
static int svc_spy_destructor(void *mem)
 
318
{
 
319
    struct svc_spy *spy = talloc_get_type(mem, struct svc_spy);
 
320
    if (!spy) {
 
321
        /* ?!?!? */
 
322
        return 0;
 
323
    }
 
324
 
 
325
    /* svc->conn has been freed, NULL the pointer in svc */
 
326
    spy->svc->conn_spy = NULL;
 
327
    spy->svc->conn = NULL;
 
328
    return 0;
 
329
}
 
330
 
 
331
static int add_svc_conn_spy(struct mt_svc *svc)
 
332
{
 
333
    struct svc_spy *spy;
 
334
 
 
335
    spy = talloc(svc->conn, struct svc_spy);
 
336
    if (!spy) return ENOMEM;
 
337
 
 
338
    spy->svc = svc;
 
339
    talloc_set_destructor((TALLOC_CTX *)spy, svc_spy_destructor);
 
340
    svc->conn_spy = spy;
 
341
 
 
342
    return EOK;
 
343
}
 
344
 
 
345
static int mark_service_as_started(struct mt_svc *svc)
 
346
{
 
347
    struct mt_ctx *ctx = svc->mt_ctx;
 
348
    struct mt_svc *iter;
 
349
    int ret;
 
350
    int i;
 
351
 
 
352
    DEBUG(5, ("Marking %s as started.\n", svc->name));
 
353
    svc->svc_started = true;
 
354
 
 
355
    /* we need to attach a spy to the connection structure so that if some code
 
356
     * frees it we can zero it out in the service structure. Otherwise we may
 
357
     * try to access or even free, freed memory. */
 
358
    ret = add_svc_conn_spy(svc);
 
359
    if (ret) {
 
360
        DEBUG(0, ("Failed to attch spy\n"));
 
361
        goto done;
 
362
    }
 
363
 
 
364
    if (!ctx->services_started) {
 
365
 
 
366
        /* check if all providers are up */
 
367
        for (iter = ctx->svc_list; iter; iter = iter->next) {
 
368
            if (iter->provider && !iter->svc_started) {
 
369
                DEBUG(5, ("Still waiting on %s provider.\n", iter->name));
 
370
                break;
 
371
            }
 
372
        }
 
373
 
 
374
        if (iter) {
 
375
            /* there are still unstarted providers */
 
376
            goto done;
 
377
        }
 
378
 
 
379
        ctx->services_started = true;
 
380
 
 
381
        DEBUG(4, ("Now starting services!\n"));
 
382
        /* then start all services */
 
383
        for (i = 0; ctx->services[i]; i++) {
 
384
            add_new_service(ctx, ctx->services[i]);
 
385
        }
 
386
    }
 
387
 
 
388
done:
 
389
    return ret;
 
390
}
 
391
 
 
392
static void services_startup_timeout(struct tevent_context *ev,
 
393
                                     struct tevent_timer *te,
 
394
                                     struct timeval t, void *ptr)
 
395
{
 
396
    struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
 
397
    int i;
 
398
 
 
399
    DEBUG(6, ("Handling timeout\n"));
 
400
 
 
401
    if (!ctx->services_started) {
 
402
 
 
403
        DEBUG(1, ("Providers did not start in time, "
 
404
                  "forcing services startup!\n"));
 
405
 
 
406
        ctx->services_started = true;
 
407
 
 
408
        DEBUG(4, ("Now starting services!\n"));
 
409
        /* then start all services */
 
410
        for (i = 0; ctx->services[i]; i++) {
 
411
            add_new_service(ctx, ctx->services[i]);
 
412
        }
 
413
    }
 
414
}
 
415
 
 
416
static int add_services_startup_timeout(struct mt_ctx *ctx)
 
417
{
 
418
    struct tevent_timer *to;
 
419
    struct timeval tv;
 
420
 
 
421
    /* 5 seconds should be plenty */
 
422
    tv = tevent_timeval_current_ofs(5, 0);
 
423
    to = tevent_add_timer(ctx->ev, ctx, tv, services_startup_timeout, ctx);
 
424
    if (!to) {
 
425
        DEBUG(0,("Out of memory?!\n"));
 
426
        return ENOMEM;
 
427
    }
 
428
 
 
429
    return EOK;
 
430
}
 
431
 
 
432
struct sbus_method monitor_methods[] = {
 
433
    { MON_SRV_METHOD_VERSION, get_monitor_version },
 
434
    { MON_SRV_METHOD_REGISTER, client_registration },
 
435
    { NULL, NULL }
 
436
};
 
437
 
 
438
struct sbus_interface monitor_server_interface = {
 
439
    MON_SRV_INTERFACE,
 
440
    MON_SRV_PATH,
 
441
    SBUS_DEFAULT_VTABLE,
 
442
    monitor_methods,
 
443
    NULL
 
444
};
 
445
 
 
446
/* monitor_dbus_init
 
447
 * Set up the monitor service as a D-BUS Server */
 
448
static int monitor_dbus_init(struct mt_ctx *ctx)
 
449
{
 
450
    char *monitor_address;
 
451
    int ret;
 
452
 
 
453
    ret = monitor_get_sbus_address(ctx, &monitor_address);
 
454
    if (ret != EOK) {
 
455
        return ret;
 
456
    }
 
457
 
 
458
    ret = sbus_new_server(ctx, ctx->ev,
 
459
                          monitor_address, &monitor_server_interface,
 
460
                          &ctx->sbus_srv, monitor_service_init, ctx);
 
461
 
 
462
    talloc_free(monitor_address);
 
463
 
 
464
    return ret;
 
465
}
 
466
 
 
467
static void svc_try_restart(struct mt_svc *svc, time_t now)
 
468
{
 
469
    int ret;
 
470
 
 
471
    DLIST_REMOVE(svc->mt_ctx->svc_list, svc);
 
472
    if (svc->last_restart != 0) {
 
473
        if ((now - svc->last_restart) > 30) { /* TODO: get val from config */
 
474
            /* it was long ago reset restart threshold */
 
475
            svc->restarts = 0;
 
476
        }
 
477
    }
 
478
 
 
479
    /* restart the process */
 
480
    if (svc->restarts > 3) { /* TODO: get val from config */
 
481
        DEBUG(0, ("Process [%s], definitely stopped!\n", svc->name));
 
482
        talloc_free(svc);
 
483
        return;
 
484
    }
 
485
 
 
486
    /* Shut down the current ping timer so it will restart
 
487
     * cleanly in start_service()
 
488
     */
 
489
    talloc_free(svc->ping_ev);
 
490
 
 
491
    ret = start_service(svc);
 
492
    if (ret != EOK) {
 
493
        DEBUG(0,("Failed to restart service '%s'\n", svc->name));
 
494
        talloc_free(svc);
 
495
        return;
 
496
    }
 
497
 
 
498
    svc->restarts++;
 
499
    svc->last_restart = now;
 
500
    return;
 
501
}
 
502
 
 
503
static void tasks_check_handler(struct tevent_context *ev,
 
504
                                struct tevent_timer *te,
 
505
                                struct timeval t, void *ptr)
 
506
{
 
507
    struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
 
508
    time_t now = time(NULL);
 
509
    bool process_alive = true;
 
510
    int ret;
 
511
 
 
512
    ret = service_check_alive(svc);
 
513
    switch (ret) {
 
514
    case EOK:
 
515
        /* all fine */
 
516
        break;
 
517
 
 
518
    case ECHILD:
 
519
        DEBUG(1,("Process (%s) is stopped!\n", svc->name));
 
520
        process_alive = false;
 
521
        break;
 
522
 
 
523
    default:
 
524
        /* TODO: should we tear down it ? */
 
525
        DEBUG(1,("Checking for service %s(%d) failed!!\n",
 
526
                 svc->name, svc->pid));
 
527
        break;
 
528
    }
 
529
 
 
530
    if (process_alive) {
 
531
        ret = service_send_ping(svc);
 
532
        switch (ret) {
 
533
        case EOK:
 
534
            /* all fine */
 
535
            break;
 
536
 
 
537
        case ENXIO:
 
538
            DEBUG(1,("Child (%s) not responding! (yet)\n", svc->name));
 
539
            break;
 
540
 
 
541
        default:
 
542
            /* TODO: should we tear it down ? */
 
543
            DEBUG(1,("Sending a message to service (%s) failed!!\n", svc->name));
 
544
            break;
 
545
        }
 
546
 
 
547
        if (svc->last_ping != 0) {
 
548
            if ((now - svc->last_ping) > (svc->ping_time)) {
 
549
                svc->failed_pongs++;
 
550
            } else {
 
551
                svc->failed_pongs = 0;
 
552
            }
 
553
            if (svc->failed_pongs > 3) {
 
554
                /* too long since we last heard of this process */
 
555
                DEBUG(1, ("Killing service [%s], not responding to pings!\n",
 
556
                          svc->name));
 
557
                monitor_kill_service(svc);
 
558
                process_alive = false;
 
559
            }
 
560
        }
 
561
 
 
562
        svc->last_ping = now;
 
563
    }
 
564
 
 
565
    if (!process_alive) {
 
566
        svc_try_restart(svc, now);
 
567
        return;
 
568
    }
 
569
 
 
570
    /* all fine, set up the task checker again */
 
571
    set_tasks_checker(svc);
 
572
}
 
573
 
 
574
static void set_tasks_checker(struct mt_svc *svc)
 
575
{
 
576
    struct tevent_timer *te = NULL;
 
577
    struct timeval tv;
 
578
 
 
579
    gettimeofday(&tv, NULL);
 
580
    tv.tv_sec += svc->ping_time;
 
581
    tv.tv_usec = 0;
 
582
    te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, tasks_check_handler, svc);
 
583
    if (te == NULL) {
 
584
        DEBUG(0, ("failed to add event, monitor offline for [%s]!\n",
 
585
                  svc->name));
 
586
        /* FIXME: shutdown ? */
 
587
    }
 
588
    svc->ping_ev = te;
 
589
}
 
590
 
 
591
static void global_checks_handler(struct tevent_context *ev,
 
592
                                  struct tevent_timer *te,
 
593
                                  struct timeval t, void *ptr)
 
594
{
 
595
    struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
 
596
    struct mt_svc *svc;
 
597
    int status;
 
598
    pid_t pid;
 
599
 
 
600
    if (!ctx->check_children) {
 
601
        goto done;
 
602
    }
 
603
 
 
604
    errno = 0;
 
605
    pid = waitpid(0, &status, WNOHANG);
 
606
    if (pid == 0) {
 
607
        goto done;
 
608
    }
 
609
 
 
610
    if (pid == -1) {
 
611
        DEBUG(0, ("waitpid returned -1 (errno:%d[%s])\n",
 
612
                  errno, strerror(errno)));
 
613
        goto done;
 
614
    }
 
615
 
 
616
    /* let's see if it is a known service, and try to restart it */
 
617
    for (svc = ctx->svc_list; svc; svc = svc->next) {
 
618
        if (svc->pid == pid) {
 
619
            time_t now = time(NULL);
 
620
            DEBUG(1, ("Service [%s] did exit\n", svc->name));
 
621
            svc_try_restart(svc, now);
 
622
            goto done;
 
623
        }
 
624
    }
 
625
    if (svc == NULL) {
 
626
        DEBUG(0, ("Unknown child (%d) did exit\n", pid));
 
627
    }
 
628
 
 
629
done:
 
630
    set_global_checker(ctx);
 
631
}
 
632
 
 
633
static void set_global_checker(struct mt_ctx *ctx)
 
634
{
 
635
    struct tevent_timer *te = NULL;
 
636
    struct timeval tv;
 
637
 
 
638
    gettimeofday(&tv, NULL);
 
639
    tv.tv_sec += 1; /* once a second */
 
640
    tv.tv_usec = 0;
 
641
    te = tevent_add_timer(ctx->ev, ctx, tv, global_checks_handler, ctx);
 
642
    if (te == NULL) {
 
643
        DEBUG(0, ("failed to add global checker event! PANIC TIME!\n"));
 
644
        /* FIXME: is this right ? shoulkd we try to clean up first ?*/
 
645
        exit(-1);
 
646
    }
 
647
}
 
648
 
 
649
static int monitor_kill_service (struct mt_svc *svc)
 
650
{
 
651
    int ret;
 
652
    ret = kill(svc->pid, SIGTERM);
 
653
    if (ret != EOK) {
 
654
        DEBUG(0,("Sending signal to child (%s:%d) failed! "
 
655
                 "Ignore and pretend child is dead.\n",
 
656
                 svc->name, svc->pid));
 
657
    }
 
658
 
 
659
    return ret;
 
660
}
 
661
 
 
662
static void reload_reply(DBusPendingCall *pending, void *data)
 
663
{
 
664
    DBusMessage *reply;
 
665
    struct mt_svc *svc = talloc_get_type(data, struct mt_svc);
 
666
 
 
667
    reply = dbus_pending_call_steal_reply(pending);
 
668
    if (!reply) {
 
669
        /* reply should never be null. This function shouldn't be called
 
670
         * until reply is valid or timeout has occurred. If reply is NULL
 
671
         * here, something is seriously wrong and we should bail out.
 
672
         */
 
673
        DEBUG(0, ("A reply callback was called but no reply was received"
 
674
                  " and no timeout occurred\n"));
 
675
        /* Destroy this connection */
 
676
        sbus_disconnect(svc->conn);
 
677
        dbus_pending_call_unref(pending);
 
678
        return;
 
679
    }
 
680
 
 
681
    /* TODO: Handle cases where the call has timed out or returned
 
682
     * with an error.
 
683
     */
 
684
 
 
685
    dbus_pending_call_unref(pending);
 
686
    dbus_message_unref(reply);
 
687
}
 
688
 
 
689
static int service_signal_dns_reload(struct mt_svc *svc);
 
690
static int monitor_update_resolv(struct config_file_ctx *file_ctx,
 
691
                          const char *filename)
 
692
{
 
693
    int ret;
 
694
    struct mt_svc *cur_svc;
 
695
    DEBUG(2, ("Resolv.conf has been updated. Reloading.\n"));
 
696
 
 
697
    ret = res_init();
 
698
    if(ret != 0) {
 
699
        return EIO;
 
700
    }
 
701
 
 
702
    /* Signal all services to reload their DNS configuration */
 
703
    for(cur_svc = file_ctx->mt_ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
 
704
        service_signal_dns_reload(cur_svc);
 
705
    }
 
706
    return EOK;
 
707
}
 
708
 
 
709
static int service_signal(struct mt_svc *svc, const char *svc_signal)
 
710
{
 
711
    DBusMessage *msg;
 
712
    int ret;
 
713
 
 
714
    if (svc->provider && strcasecmp(svc->provider, "local") == 0) {
 
715
        /* The local provider requires no signaling */
 
716
        return EOK;
 
717
    }
 
718
 
 
719
    if (!svc->conn) {
 
720
        /* Avoid a race condition where we are trying to
 
721
         * order a service to reload that hasn't started
 
722
         * yet.
 
723
         */
 
724
        DEBUG(1,("Could not signal service [%s].\n", svc->name));
 
725
        return EIO;
 
726
    }
 
727
 
 
728
    msg = dbus_message_new_method_call(NULL,
 
729
                                       MONITOR_PATH,
 
730
                                       MONITOR_INTERFACE,
 
731
                                       svc_signal);
 
732
    if (!msg) {
 
733
        DEBUG(0,("Out of memory?!\n"));
 
734
        monitor_kill_service(svc);
 
735
        talloc_free(svc);
 
736
        return ENOMEM;
 
737
    }
 
738
 
 
739
    ret = sbus_conn_send(svc->conn, msg,
 
740
                         svc->mt_ctx->service_id_timeout,
 
741
                         reload_reply, svc, NULL);
 
742
 
 
743
    dbus_message_unref(msg);
 
744
    return ret;
 
745
}
 
746
 
 
747
static int service_signal_dns_reload(struct mt_svc *svc)
 
748
{
 
749
    return service_signal(svc, MON_CLI_METHOD_RES_INIT);
 
750
}
 
751
static int service_signal_offline(struct mt_svc *svc)
 
752
{
 
753
    return service_signal(svc, MON_CLI_METHOD_OFFLINE);
 
754
}
 
755
static int service_signal_reset_offline(struct mt_svc *svc)
 
756
{
 
757
    return service_signal(svc, MON_CLI_METHOD_RESET_OFFLINE);
 
758
}
 
759
static int service_signal_rotate(struct mt_svc *svc)
 
760
{
 
761
    return service_signal(svc, MON_CLI_METHOD_ROTATE);
 
762
}
 
763
 
 
764
static int check_domain_ranges(struct sss_domain_info *domains)
 
765
{
 
766
    struct sss_domain_info *dom = domains, *other = NULL;
 
767
    uint32_t id_min, id_max;
 
768
 
 
769
    while (dom) {
 
770
        other = dom->next;
 
771
        if (dom->id_max && dom->id_min > dom->id_max) {
 
772
            DEBUG(1, ("Domain '%s' does not have a valid ID range\n",
 
773
                      dom->name));
 
774
            return EINVAL;
 
775
        }
 
776
 
 
777
        while (other) {
 
778
            id_min = MAX(dom->id_min, other->id_min);
 
779
            id_max = MIN((dom->id_max ? dom->id_max : UINT32_MAX),
 
780
                         (other->id_max ? other->id_max : UINT32_MAX));
 
781
            if (id_min <= id_max) {
 
782
                DEBUG(1, ("Domains '%s' and '%s' overlap in range %u - %u\n",
 
783
                          dom->name, other->name, id_min, id_max));
 
784
            }
 
785
            other = other->next;
 
786
        }
 
787
        dom = dom->next;
 
788
    }
 
789
 
 
790
    return EOK;
 
791
}
 
792
 
 
793
static int check_local_domain_unique(struct sss_domain_info *domains)
 
794
{
 
795
    uint8_t count = 0;
 
796
 
 
797
    struct sss_domain_info *dom = domains;
 
798
 
 
799
    while (dom) {
 
800
        if (strcasecmp(dom->provider, "local") == 0) {
 
801
            count++;
 
802
        }
 
803
 
 
804
        if (count > 1) {
 
805
            break;
 
806
        }
 
807
 
 
808
        dom = dom->next;
 
809
    }
 
810
 
 
811
    if (count > 1) {
 
812
        return EINVAL;
 
813
    }
 
814
 
 
815
    return EOK;
 
816
}
 
817
 
 
818
static char *check_services(char **services)
 
819
{
 
820
    const char *known_services[] = { "nss", "pam", NULL };
 
821
    int i;
 
822
    int ii;
 
823
 
 
824
    /* Check if services we are about to start are in the list if known */
 
825
    for (i = 0; services[i]; i++) {
 
826
        for (ii=0; known_services[ii]; ii++) {
 
827
            if (strcasecmp(services[i], known_services[ii]) == 0) {
 
828
                break;
 
829
            }
 
830
        }
 
831
 
 
832
        if (known_services[ii] == NULL) {
 
833
            return services[i];
 
834
        }
 
835
    }
 
836
 
 
837
    return NULL;
 
838
}
 
839
 
 
840
int get_monitor_config(struct mt_ctx *ctx)
 
841
{
 
842
    int ret;
 
843
    int timeout_seconds;
 
844
    char *badsrv = NULL;
 
845
 
 
846
    ret = confdb_get_int(ctx->cdb, ctx,
 
847
                         CONFDB_MONITOR_CONF_ENTRY,
 
848
                         CONFDB_MONITOR_SBUS_TIMEOUT,
 
849
                         10, &timeout_seconds);
 
850
    if (ret != EOK) {
 
851
        return ret;
 
852
    }
 
853
 
 
854
    ctx->service_id_timeout = timeout_seconds * 1000; /* service_id_timeout is in ms */
 
855
 
 
856
    ctx->service_ctx = talloc_new(ctx);
 
857
    if(!ctx->service_ctx) {
 
858
        return ENOMEM;
 
859
    }
 
860
    ret = confdb_get_string_as_list(ctx->cdb, ctx->service_ctx,
 
861
                                    CONFDB_MONITOR_CONF_ENTRY,
 
862
                                    CONFDB_MONITOR_ACTIVE_SERVICES,
 
863
                                    &ctx->services);
 
864
    if (ret != EOK) {
 
865
        DEBUG(0, ("No services configured!\n"));
 
866
        return EINVAL;
 
867
    }
 
868
 
 
869
    badsrv = check_services(ctx->services);
 
870
    if (badsrv != NULL) {
 
871
        DEBUG(0, ("Invalid service %s\n", badsrv));
 
872
        return EINVAL;
 
873
    }
 
874
 
 
875
    ctx->domain_ctx = talloc_new(ctx);
 
876
    if(!ctx->domain_ctx) {
 
877
        return ENOMEM;
 
878
    }
 
879
    ret = confdb_get_domains(ctx->cdb, &ctx->domains);
 
880
    if (ret != EOK) {
 
881
        DEBUG(0, ("No domains configured.\n"));
 
882
        return ret;
 
883
    }
 
884
 
 
885
    ret = check_local_domain_unique(ctx->domains);
 
886
    if (ret != EOK) {
 
887
        DEBUG(0, ("More than one local domain configured.\n"));
 
888
        return ret;
 
889
    }
 
890
 
 
891
    /* Check UID/GID overlaps */
 
892
    ret = check_domain_ranges(ctx->domains);
 
893
    if (ret != EOK) {
 
894
        return ret;
 
895
    }
 
896
 
 
897
    return EOK;
 
898
}
 
899
 
 
900
static int get_service_config(struct mt_ctx *ctx, const char *name,
 
901
                              struct mt_svc **svc_cfg)
 
902
{
 
903
    int ret;
 
904
    char *path;
 
905
    struct mt_svc *svc;
 
906
 
 
907
    *svc_cfg = NULL;
 
908
 
 
909
    svc = talloc_zero(ctx, struct mt_svc);
 
910
    if (!svc) {
 
911
        return ENOMEM;
 
912
    }
 
913
    svc->mt_ctx = ctx;
 
914
 
 
915
    talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
 
916
 
 
917
    svc->name = talloc_strdup(svc, name);
 
918
    if (!svc->name) {
 
919
        talloc_free(svc);
 
920
        return ENOMEM;
 
921
    }
 
922
 
 
923
    svc->identity = talloc_strdup(svc, name);
 
924
    if (!svc->identity) {
 
925
        talloc_free(svc);
 
926
        return ENOMEM;
 
927
    }
 
928
 
 
929
    path = talloc_asprintf(svc, CONFDB_SERVICE_PATH_TMPL, svc->name);
 
930
    if (!path) {
 
931
        talloc_free(svc);
 
932
        return ENOMEM;
 
933
    }
 
934
 
 
935
    ret = confdb_get_string(ctx->cdb, svc, path,
 
936
                            CONFDB_SERVICE_COMMAND,
 
937
                            NULL, &svc->command);
 
938
    if (ret != EOK) {
 
939
        DEBUG(0,("Failed to start service '%s'\n", svc->name));
 
940
        talloc_free(svc);
 
941
        return ret;
 
942
    }
 
943
 
 
944
    if (!svc->command) {
 
945
        svc->command = talloc_asprintf(svc, "%s/sssd_%s -d %d%s%s",
 
946
                                       SSSD_LIBEXEC_PATH,
 
947
                                       svc->name, debug_level,
 
948
                                       (debug_timestamps?
 
949
                                              "": " --debug-timestamps=0"),
 
950
                                       (debug_to_file ?
 
951
                                              " --debug-to-files":""));
 
952
        if (!svc->command) {
 
953
            talloc_free(svc);
 
954
            return ENOMEM;
 
955
        }
 
956
    }
 
957
 
 
958
    ret = confdb_get_int(ctx->cdb, svc, path,
 
959
                         CONFDB_SERVICE_TIMEOUT,
 
960
                         MONITOR_DEF_PING_TIME, &svc->ping_time);
 
961
    if (ret != EOK) {
 
962
        DEBUG(0,("Failed to start service '%s'\n", svc->name));
 
963
        talloc_free(svc);
 
964
        return ret;
 
965
    }
 
966
 
 
967
    /* 'timeout = 0' should be translated to the default */
 
968
    if (svc->ping_time == 0) {
 
969
        svc->ping_time = MONITOR_DEF_PING_TIME;
 
970
    }
 
971
 
 
972
    *svc_cfg = svc;
 
973
    talloc_free(path);
 
974
 
 
975
    return EOK;
 
976
}
 
977
 
 
978
static int add_new_service(struct mt_ctx *ctx, const char *name)
 
979
{
 
980
    int ret;
 
981
    struct mt_svc *svc;
 
982
 
 
983
    ret = get_service_config(ctx, name, &svc);
 
984
    if (ret != EOK) {
 
985
        return ret;
 
986
    }
 
987
 
 
988
    ret = start_service(svc);
 
989
    if (ret != EOK) {
 
990
        DEBUG(0,("Failed to start service '%s'\n", svc->name));
 
991
        talloc_free(svc);
 
992
    }
 
993
 
 
994
    return ret;
 
995
}
 
996
 
 
997
static int get_provider_config(struct mt_ctx *ctx, const char *name,
 
998
                              struct mt_svc **svc_cfg)
 
999
{
 
1000
    int ret;
 
1001
    char *path;
 
1002
    struct mt_svc *svc;
 
1003
 
 
1004
    *svc_cfg = NULL;
 
1005
 
 
1006
    svc = talloc_zero(ctx, struct mt_svc);
 
1007
    if (!svc) {
 
1008
        return ENOMEM;
 
1009
    }
 
1010
    svc->mt_ctx = ctx;
 
1011
 
 
1012
    talloc_set_destructor((TALLOC_CTX *)svc, svc_destructor);
 
1013
 
 
1014
    svc->name = talloc_strdup(svc, name);
 
1015
    if (!svc->name) {
 
1016
        talloc_free(svc);
 
1017
        return ENOMEM;
 
1018
    }
 
1019
 
 
1020
    svc->identity = talloc_asprintf(svc, "%%BE_%s", svc->name);
 
1021
    if (!svc->identity) {
 
1022
        talloc_free(svc);
 
1023
        return ENOMEM;
 
1024
    }
 
1025
 
 
1026
    path = talloc_asprintf(svc, CONFDB_DOMAIN_PATH_TMPL, name);
 
1027
    if (!path) {
 
1028
        talloc_free(svc);
 
1029
        return ENOMEM;
 
1030
    }
 
1031
 
 
1032
    ret = confdb_get_string(ctx->cdb, svc, path,
 
1033
                            CONFDB_DOMAIN_ID_PROVIDER,
 
1034
                            NULL, &svc->provider);
 
1035
    if (ret != EOK) {
 
1036
        DEBUG(0, ("Failed to find ID provider from [%s] configuration\n", name));
 
1037
        talloc_free(svc);
 
1038
        return ret;
 
1039
    }
 
1040
 
 
1041
    ret = confdb_get_string(ctx->cdb, svc, path,
 
1042
                            CONFDB_DOMAIN_COMMAND,
 
1043
                            NULL, &svc->command);
 
1044
    if (ret != EOK) {
 
1045
        DEBUG(0, ("Failed to find command from [%s] configuration\n", name));
 
1046
        talloc_free(svc);
 
1047
        return ret;
 
1048
    }
 
1049
 
 
1050
    ret = confdb_get_int(ctx->cdb, svc, path,
 
1051
                         CONFDB_DOMAIN_TIMEOUT,
 
1052
                         MONITOR_DEF_PING_TIME, &svc->ping_time);
 
1053
    if (ret != EOK) {
 
1054
        DEBUG(0,("Failed to start service '%s'\n", svc->name));
 
1055
        talloc_free(svc);
 
1056
        return ret;
 
1057
    }
 
1058
 
 
1059
    /* 'timeout = 0' should be translated to the default */
 
1060
    if (svc->ping_time == 0) {
 
1061
        svc->ping_time = MONITOR_DEF_PING_TIME;
 
1062
    }
 
1063
 
 
1064
    talloc_free(path);
 
1065
 
 
1066
    /* if no provider is present do not run the domain */
 
1067
    if (!svc->provider) {
 
1068
        talloc_free(svc);
 
1069
        return EIO;
 
1070
    }
 
1071
 
 
1072
    /* if there are no custom commands, build a default one */
 
1073
    if (!svc->command) {
 
1074
        svc->command = talloc_asprintf(svc,
 
1075
                            "%s/sssd_be -d %d%s%s --domain %s",
 
1076
                            SSSD_LIBEXEC_PATH, debug_level,
 
1077
                            (debug_timestamps?"": " --debug-timestamps=0"),
 
1078
                            (debug_to_file?" --debug-to-files":""),
 
1079
                            svc->name);
 
1080
        if (!svc->command) {
 
1081
            talloc_free(svc);
 
1082
            return ENOMEM;
 
1083
        }
 
1084
    }
 
1085
 
 
1086
    *svc_cfg = svc;
 
1087
    return EOK;
 
1088
}
 
1089
 
 
1090
static int add_new_provider(struct mt_ctx *ctx, const char *name)
 
1091
{
 
1092
    int ret;
 
1093
    struct mt_svc *svc;
 
1094
 
 
1095
    ret = get_provider_config(ctx, name, &svc);
 
1096
    if (ret != EOK) {
 
1097
        DEBUG(0, ("Could not get provider configuration for [%s]\n",
 
1098
                  name));
 
1099
        return ret;
 
1100
    }
 
1101
 
 
1102
    if (strcasecmp(svc->provider, "local") == 0) {
 
1103
        /* The LOCAL provider requires no back-end currently
 
1104
         * We'll add it to the service list, but we don't need
 
1105
         * to poll it.
 
1106
         */
 
1107
        svc->svc_started = true;
 
1108
        DLIST_ADD(ctx->svc_list, svc);
 
1109
        return ENOENT;
 
1110
    }
 
1111
 
 
1112
    ret = start_service(svc);
 
1113
    if (ret != EOK) {
 
1114
        DEBUG(0,("Failed to start service '%s'\n", svc->name));
 
1115
        talloc_free(svc);
 
1116
    }
 
1117
 
 
1118
    return ret;
 
1119
}
 
1120
 
 
1121
static void monitor_hup(struct tevent_context *ev,
 
1122
                        struct tevent_signal *se,
 
1123
                        int signum,
 
1124
                        int count,
 
1125
                        void *siginfo,
 
1126
                        void *private_data)
 
1127
{
 
1128
    struct mt_ctx *ctx = talloc_get_type(private_data, struct mt_ctx);
 
1129
    struct mt_svc *cur_svc;
 
1130
 
 
1131
    DEBUG(1, ("Received SIGHUP.\n"));
 
1132
 
 
1133
    /* Signal all services to rotate debug files */
 
1134
    for(cur_svc = ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
 
1135
        service_signal_rotate(cur_svc);
 
1136
    }
 
1137
}
 
1138
 
 
1139
static int monitor_cleanup(void)
 
1140
{
 
1141
    char *file;
 
1142
    int ret;
 
1143
    TALLOC_CTX *tmp_ctx;
 
1144
 
 
1145
    tmp_ctx = talloc_new(NULL);
 
1146
    if (!tmp_ctx) return ENOMEM;
 
1147
 
 
1148
    file = talloc_asprintf(tmp_ctx, "%s/%s.pid", PID_PATH, "sssd");
 
1149
    if (file == NULL) {
 
1150
        return ENOMEM;
 
1151
    }
 
1152
 
 
1153
    errno = 0;
 
1154
    ret = unlink(file);
 
1155
    if (ret == -1) {
 
1156
        ret = errno;
 
1157
        DEBUG(0, ("Error removing pidfile! (%d [%s])\n",
 
1158
                ret, strerror(ret)));
 
1159
        talloc_free(file);
 
1160
        return errno;
 
1161
    }
 
1162
 
 
1163
    talloc_free(file);
 
1164
    return EOK;
 
1165
}
 
1166
 
 
1167
static void monitor_quit(struct tevent_context *ev,
 
1168
                         struct tevent_signal *se,
 
1169
                         int signum,
 
1170
                         int count,
 
1171
                         void *siginfo,
 
1172
                         void *private_data)
 
1173
{
 
1174
    struct mt_ctx *mt_ctx = talloc_get_type(private_data, struct mt_ctx);
 
1175
    struct mt_svc *svc;
 
1176
    pid_t pid;
 
1177
    int status;
 
1178
    errno_t error;
 
1179
    int kret;
 
1180
    bool killed;
 
1181
 
 
1182
    DEBUG(8, ("Received shutdown command\n"));
 
1183
 
 
1184
    DEBUG(0, ("Monitor received %s: terminating children\n",
 
1185
              strsignal(signum)));
 
1186
 
 
1187
    /* Kill all of our known children manually */
 
1188
    DLIST_FOR_EACH(svc, mt_ctx->svc_list) {
 
1189
        if (svc->pid == 0) {
 
1190
            /* The local provider has no PID */
 
1191
            continue;
 
1192
        }
 
1193
 
 
1194
        killed = false;
 
1195
        DEBUG(1, ("Terminating [%s][%d]\n", svc->name, svc->pid));
 
1196
        do {
 
1197
            errno = 0;
 
1198
            kret = kill(svc->pid, SIGTERM);
 
1199
            if (kret < 0) {
 
1200
                error = errno;
 
1201
                DEBUG(1, ("Couldn't kill [%s][%d]: [%s]\n",
 
1202
                          svc->name, svc->pid, strerror(error)));
 
1203
            }
 
1204
 
 
1205
            error = 0;
 
1206
            do {
 
1207
                errno = 0;
 
1208
                pid = waitpid(svc->pid, &status, WNOHANG);
 
1209
                if (pid == -1) {
 
1210
                    /* An error occurred while waiting */
 
1211
                    error = errno;
 
1212
                    if (error != EINTR) {
 
1213
                        DEBUG(0, ("[%d][%s] while waiting for [%s]\n",
 
1214
                                  error, strerror(error), svc->name));
 
1215
                        /* Forcibly kill this child */
 
1216
                        kill(svc->pid, SIGKILL);
 
1217
                        break;
 
1218
                    }
 
1219
                } else if (pid != 0) {
 
1220
                    error = 0;
 
1221
                    if WIFEXITED(status) {
 
1222
                        DEBUG(1, ("Child [%s] exited gracefully\n", svc->name));
 
1223
                    } else if WIFSIGNALED(status) {
 
1224
                        DEBUG(1, ("Child [%s] terminated with a signal\n", svc->name));
 
1225
                    } else {
 
1226
                        DEBUG(0, ("Child [%s] did not exit cleanly\n", svc->name));
 
1227
                        /* Forcibly kill this child */
 
1228
                        kill(svc->pid, SIGKILL);
 
1229
                    }
 
1230
                    killed = true;
 
1231
                }
 
1232
            } while (error == EINTR);
 
1233
            if (!killed) {
 
1234
                /* Sleep 10ms and try again */
 
1235
                usleep(10000);
 
1236
            }
 
1237
        } while (!killed);
 
1238
    }
 
1239
 
 
1240
#if HAVE_GETPGRP
 
1241
    /* Kill any remaining children in our process group, just in case
 
1242
     * we have any leftover children we don't expect. For example, if
 
1243
     * a krb5_child or ldap_child is running at the same moment.
 
1244
     */
 
1245
    error = 0;
 
1246
    if (getpgrp() == getpid()) {
 
1247
        kill(-getpgrp(), SIGTERM);
 
1248
        do {
 
1249
            errno = 0;
 
1250
            pid = waitpid(0, &status, 0);
 
1251
            if (pid == -1) {
 
1252
                error = errno;
 
1253
            }
 
1254
        } while (error == EINTR || pid > 0);
 
1255
    }
 
1256
#endif
 
1257
 
 
1258
    monitor_cleanup();
 
1259
 
 
1260
    exit(0);
 
1261
}
 
1262
 
 
1263
static void signal_offline(struct tevent_context *ev,
 
1264
                           struct tevent_signal *se,
 
1265
                           int signum,
 
1266
                           int count,
 
1267
                           void *siginfo,
 
1268
                           void *private_data)
 
1269
{
 
1270
    struct mt_ctx *monitor;
 
1271
    struct mt_svc *cur_svc;
 
1272
 
 
1273
    monitor = talloc_get_type(private_data, struct mt_ctx);
 
1274
 
 
1275
    DEBUG(8, ("Signaling providers to go offline immediately.\n"));
 
1276
 
 
1277
    /* Signal all providers to immediately go offline */
 
1278
    for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
 
1279
        /* Don't signal services, only providers */
 
1280
        if (cur_svc->provider) {
 
1281
            service_signal_offline(cur_svc);
 
1282
        }
 
1283
    }
 
1284
}
 
1285
 
 
1286
static void signal_offline_reset(struct tevent_context *ev,
 
1287
                                 struct tevent_signal *se,
 
1288
                                 int signum,
 
1289
                                 int count,
 
1290
                                 void *siginfo,
 
1291
                                 void *private_data)
 
1292
{
 
1293
    struct mt_ctx *monitor;
 
1294
    struct mt_svc *cur_svc;
 
1295
 
 
1296
    monitor = talloc_get_type(private_data, struct mt_ctx);
 
1297
 
 
1298
    DEBUG(8, ("Signaling providers to reset offline immediately.\n"));
 
1299
 
 
1300
    for(cur_svc = monitor->svc_list; cur_svc; cur_svc = cur_svc->next) {
 
1301
        if (cur_svc->provider) {
 
1302
            service_signal_reset_offline(cur_svc);
 
1303
        }
 
1304
    }
 
1305
}
 
1306
 
 
1307
int read_config_file(const char *config_file)
 
1308
{
 
1309
    int ret;
 
1310
    struct collection_item *sssd_config = NULL;
 
1311
    struct collection_item *error_list = NULL;
 
1312
 
 
1313
    /* Read the configuration into a collection */
 
1314
    ret = config_from_file("sssd", config_file, &sssd_config,
 
1315
                           INI_STOP_ON_ANY, &error_list);
 
1316
    if (ret != EOK) {
 
1317
        DEBUG(0, ("Parse error reading configuration file [%s]\n",
 
1318
                  config_file));
 
1319
        print_file_parsing_errors(stderr, error_list);
 
1320
    }
 
1321
 
 
1322
    free_ini_config_errors(error_list);
 
1323
    free_ini_config(sssd_config);
 
1324
    return ret;
 
1325
}
 
1326
 
 
1327
static int monitor_ctx_destructor(void *mem)
 
1328
{
 
1329
    struct mt_ctx *mon = talloc_get_type(mem, struct mt_ctx);
 
1330
    struct mt_svc *svc;
 
1331
 
 
1332
    /* zero out references in svcs so that they don't try
 
1333
     * to access the monitor context on process shutdown */
 
1334
 
 
1335
    for (svc = mon->svc_list; svc; svc = svc->next) {
 
1336
        svc->mt_ctx = NULL;
 
1337
    }
 
1338
    return 0;
 
1339
}
 
1340
 
 
1341
static errno_t load_configuration(TALLOC_CTX *mem_ctx,
 
1342
                                  const char *config_file,
 
1343
                                  struct mt_ctx **monitor)
 
1344
{
 
1345
    errno_t ret;
 
1346
    struct mt_ctx *ctx;
 
1347
    char *cdb_file = NULL;
 
1348
 
 
1349
    ctx = talloc_zero(mem_ctx, struct mt_ctx);
 
1350
    if(!ctx) {
 
1351
        return ENOMEM;
 
1352
    }
 
1353
    talloc_set_destructor((TALLOC_CTX *)ctx, monitor_ctx_destructor);
 
1354
 
 
1355
    cdb_file = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
 
1356
    if (cdb_file == NULL) {
 
1357
        DEBUG(0,("Out of memory, aborting!\n"));
 
1358
        ret = ENOMEM;
 
1359
        goto done;
 
1360
    }
 
1361
 
 
1362
    ret = confdb_init(ctx, &ctx->cdb, cdb_file);
 
1363
    if (ret != EOK) {
 
1364
        DEBUG(0,("The confdb initialization failed\n"));
 
1365
        goto done;
 
1366
    }
 
1367
 
 
1368
    /* Initialize the CDB from the configuration file */
 
1369
    ret = confdb_test(ctx->cdb);
 
1370
    if (ret == ENOENT) {
 
1371
        /* First-time setup */
 
1372
 
 
1373
        /* Purge any existing confdb in case an old
 
1374
         * misconfiguration gets in the way
 
1375
         */
 
1376
        talloc_zfree(ctx->cdb);
 
1377
        unlink(cdb_file);
 
1378
 
 
1379
        ret = confdb_init(ctx, &ctx->cdb, cdb_file);
 
1380
        if (ret != EOK) {
 
1381
            DEBUG(0,("The confdb initialization failed\n"));
 
1382
            goto done;
 
1383
        }
 
1384
 
 
1385
        /* Load special entries */
 
1386
        ret = confdb_create_base(ctx->cdb);
 
1387
        if (ret != EOK) {
 
1388
            DEBUG(0, ("Unable to load special entries into confdb\n"));
 
1389
            goto done;
 
1390
        }
 
1391
    } else if (ret != EOK) {
 
1392
        DEBUG(0, ("Fatal error initializing confdb\n"));
 
1393
        goto done;
 
1394
    }
 
1395
    talloc_zfree(cdb_file);
 
1396
 
 
1397
    ret = confdb_init_db(config_file, ctx->cdb);
 
1398
    if (ret != EOK) {
 
1399
        DEBUG(0, ("ConfDB initialization has failed [%s]\n",
 
1400
              strerror(ret)));
 
1401
        goto done;
 
1402
    }
 
1403
 
 
1404
    /* Validate the configuration in the database */
 
1405
    /* Read in the monitor's configuration */
 
1406
    ret = get_monitor_config(ctx);
 
1407
    if (ret != EOK) {
 
1408
        goto done;
 
1409
    }
 
1410
 
 
1411
    *monitor = ctx;
 
1412
 
 
1413
    ret = EOK;
 
1414
 
 
1415
done:
 
1416
    if (ret != EOK) {
 
1417
        talloc_free(ctx);
 
1418
    }
 
1419
    return ret;
 
1420
}
 
1421
 
 
1422
#ifdef HAVE_SYS_INOTIFY_H
 
1423
static void process_config_file(struct tevent_context *ev,
 
1424
                                struct tevent_timer *te,
 
1425
                                struct timeval t, void *ptr);
 
1426
 
 
1427
static void config_file_changed(struct tevent_context *ev,
 
1428
                                struct tevent_fd *fde,
 
1429
                                uint16_t flags, void *data)
 
1430
{
 
1431
    struct tevent_timer *te = NULL;
 
1432
    struct timeval tv;
 
1433
    struct config_file_ctx *file_ctx;
 
1434
 
 
1435
    file_ctx = talloc_get_type(data, struct config_file_ctx);
 
1436
    if (file_ctx->needs_update) {
 
1437
        /* Skip updating. It's already queued for update.
 
1438
         */
 
1439
        return;
 
1440
    }
 
1441
 
 
1442
    /* We will queue the file for update in one second.
 
1443
     * This way, if there is a script writing to the file
 
1444
     * repeatedly, we won't be attempting to update multiple
 
1445
     * times.
 
1446
     */
 
1447
    gettimeofday(&tv, NULL);
 
1448
    tv.tv_sec += 1;
 
1449
 
 
1450
    te = tevent_add_timer(ev, ev, tv, process_config_file, file_ctx);
 
1451
    if (!te) {
 
1452
        DEBUG(0, ("Unable to queue config file update! Exiting.\n"));
 
1453
        kill(getpid(), SIGTERM);
 
1454
        return;
 
1455
    }
 
1456
    file_ctx->needs_update = 1;
 
1457
}
 
1458
 
 
1459
struct rewatch_ctx {
 
1460
    struct config_file_callback *cb;
 
1461
    struct config_file_ctx *file_ctx;
 
1462
};
 
1463
static void rewatch_config_file(struct tevent_context *ev,
 
1464
                                struct tevent_timer *te,
 
1465
                                struct timeval t, void *ptr);
 
1466
static void process_config_file(struct tevent_context *ev,
 
1467
                                struct tevent_timer *te,
 
1468
                                struct timeval t, void *ptr)
 
1469
{
 
1470
    TALLOC_CTX *tmp_ctx;
 
1471
    struct inotify_event *in_event;
 
1472
    char *buf;
 
1473
    char *name;
 
1474
    ssize_t len, total_len;
 
1475
    ssize_t event_size;
 
1476
    struct config_file_ctx *file_ctx;
 
1477
    struct config_file_callback *cb;
 
1478
    struct rewatch_ctx *rw_ctx;
 
1479
 
 
1480
    event_size = sizeof(struct inotify_event);
 
1481
    file_ctx = talloc_get_type(ptr, struct config_file_ctx);
 
1482
 
 
1483
    DEBUG(1, ("Processing config file changes\n"));
 
1484
 
 
1485
    tmp_ctx = talloc_new(NULL);
 
1486
    if (!tmp_ctx) return;
 
1487
 
 
1488
    buf = talloc_size(tmp_ctx, event_size);
 
1489
    if (!buf) {
 
1490
        goto done;
 
1491
    }
 
1492
 
 
1493
    total_len = 0;
 
1494
    while (total_len < event_size) {
 
1495
        len = read(file_ctx->mt_ctx->inotify_fd, buf+total_len,
 
1496
                   event_size-total_len);
 
1497
        if (len == -1) {
 
1498
            if (errno == EINTR || errno == EAGAIN) continue;
 
1499
            DEBUG(0, ("Critical error reading inotify file descriptor.\n"));
 
1500
            goto done;
 
1501
        }
 
1502
        total_len += len;
 
1503
    }
 
1504
 
 
1505
    in_event = (struct inotify_event *)buf;
 
1506
 
 
1507
    if (in_event->len > 0) {
 
1508
        /* Read in the name, even though we don't use it,
 
1509
         * so that read ptr is in the right place
 
1510
         */
 
1511
        name = talloc_size(tmp_ctx, len);
 
1512
        if (!name) {
 
1513
            goto done;
 
1514
        }
 
1515
        total_len = 0;
 
1516
        while (total_len < in_event->len) {
 
1517
            len = read(file_ctx->mt_ctx->inotify_fd, &name, in_event->len);
 
1518
            if (len == -1) {
 
1519
                if (errno == EINTR || errno == EAGAIN) continue;
 
1520
                DEBUG(0, ("Critical error reading inotify file descriptor.\n"));
 
1521
                goto done;
 
1522
            }
 
1523
            total_len += len;
 
1524
        }
 
1525
    }
 
1526
 
 
1527
    for (cb = file_ctx->callbacks; cb; cb = cb->next) {
 
1528
        if (cb->wd == in_event->wd) {
 
1529
            break;
 
1530
        }
 
1531
    }
 
1532
    if (!cb) {
 
1533
        DEBUG(0, ("Unknown watch descriptor\n"));
 
1534
        goto done;
 
1535
    }
 
1536
 
 
1537
    if (in_event->mask & IN_IGNORED) {
 
1538
        /* Some text editors will move a new file on top of the
 
1539
         * existing one instead of modifying it. In this case,
 
1540
         * the kernel will send us an IN_IGNORE signal.
 
1541
         * We will try to open a new watch descriptor on the
 
1542
         * new file.
 
1543
         */
 
1544
        struct timeval tv;
 
1545
        struct tevent_timer *tev;
 
1546
        tv.tv_sec = t.tv_sec+5;
 
1547
        tv.tv_usec = t.tv_usec;
 
1548
 
 
1549
        cb->retries = 0;
 
1550
        rw_ctx = talloc(file_ctx, struct rewatch_ctx);
 
1551
        if(!rw_ctx) {
 
1552
            DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
 
1553
            close(file_ctx->mt_ctx->inotify_fd);
 
1554
            kill(getpid(), SIGTERM);
 
1555
            goto done;
 
1556
        }
 
1557
        rw_ctx->cb = cb;
 
1558
        rw_ctx->file_ctx = file_ctx;
 
1559
 
 
1560
        tev = tevent_add_timer(ev, rw_ctx, tv, rewatch_config_file, rw_ctx);
 
1561
        if (tev == NULL) {
 
1562
            DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
 
1563
            close(file_ctx->mt_ctx->inotify_fd);
 
1564
            kill(getpid(), SIGTERM);
 
1565
        }
 
1566
        goto done;
 
1567
    }
 
1568
 
 
1569
    /* Tell the monitor to signal the children */
 
1570
    cb->fn(file_ctx, cb->filename);
 
1571
    file_ctx->needs_update = 0;
 
1572
 
 
1573
done:
 
1574
    talloc_free(tmp_ctx);
 
1575
}
 
1576
 
 
1577
static void rewatch_config_file(struct tevent_context *ev,
 
1578
                                struct tevent_timer *te,
 
1579
                                struct timeval t, void *ptr)
 
1580
{
 
1581
    int err;
 
1582
    struct tevent_timer *tev = NULL;
 
1583
    struct timeval tv;
 
1584
    struct config_file_callback *cb;
 
1585
 
 
1586
    struct rewatch_ctx *rw_ctx;
 
1587
    struct config_file_ctx *file_ctx;
 
1588
 
 
1589
    rw_ctx = talloc_get_type(ptr, struct rewatch_ctx);
 
1590
 
 
1591
    cb = rw_ctx->cb;
 
1592
    file_ctx = rw_ctx->file_ctx;
 
1593
 
 
1594
    /* Retry six times at five-second intervals before giving up */
 
1595
    cb->retries++;
 
1596
    if (cb->retries > 6) {
 
1597
        DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
 
1598
        close(file_ctx->mt_ctx->inotify_fd);
 
1599
        kill(getpid(), SIGTERM);
 
1600
    }
 
1601
 
 
1602
    cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
 
1603
                               cb->filename, IN_MODIFY);
 
1604
    if (cb->wd < 0) {
 
1605
        err = errno;
 
1606
 
 
1607
        tv.tv_sec = t.tv_sec+5;
 
1608
        tv.tv_usec = t.tv_usec;
 
1609
 
 
1610
        DEBUG(1, ("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
 
1611
                  cb->filename, err, strerror(err)));
 
1612
 
 
1613
        tev = tevent_add_timer(ev, ev, tv, rewatch_config_file, rw_ctx);
 
1614
        if (tev == NULL) {
 
1615
            DEBUG(0, ("Could not restore inotify watch. Quitting!\n"));
 
1616
            close(file_ctx->mt_ctx->inotify_fd);
 
1617
            kill(getpid(), SIGTERM);
 
1618
        }
 
1619
 
 
1620
        return;
 
1621
    }
 
1622
    cb->retries = 0;
 
1623
 
 
1624
    /* Tell the monitor to signal the children */
 
1625
    cb->fn(file_ctx, cb->filename);
 
1626
 
 
1627
    talloc_free(rw_ctx);
 
1628
    file_ctx->needs_update = 0;
 
1629
}
 
1630
#endif
 
1631
 
 
1632
static void poll_config_file(struct tevent_context *ev,
 
1633
                                    struct tevent_timer *te,
 
1634
                                    struct timeval t, void *ptr)
 
1635
{
 
1636
    int ret, err;
 
1637
    struct stat file_stat;
 
1638
    struct timeval tv;
 
1639
    struct config_file_ctx *file_ctx;
 
1640
    struct config_file_callback *cb;
 
1641
 
 
1642
    file_ctx = talloc_get_type(ptr,struct config_file_ctx);
 
1643
 
 
1644
    for (cb = file_ctx->callbacks; cb; cb = cb->next) {
 
1645
        ret = stat(cb->filename, &file_stat);
 
1646
        if (ret < 0) {
 
1647
            err = errno;
 
1648
            DEBUG(0, ("Could not stat file [%s]. Error [%d:%s]\n",
 
1649
                      cb->filename, err, strerror(err)));
 
1650
            /* TODO: If the config file is missing, should we shut down? */
 
1651
            return;
 
1652
        }
 
1653
 
 
1654
        if (file_stat.st_mtime != cb->modified) {
 
1655
            /* Parse the configuration file and signal the children */
 
1656
            /* Note: this will fire if the modification time changes into the past
 
1657
             * as well as the future.
 
1658
             */
 
1659
            DEBUG(1, ("Config file changed\n"));
 
1660
            cb->modified = file_stat.st_mtime;
 
1661
 
 
1662
            /* Tell the monitor to signal the children */
 
1663
            cb->fn(file_ctx, cb->filename);
 
1664
        }
 
1665
    }
 
1666
 
 
1667
    gettimeofday(&tv, NULL);
 
1668
    tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
 
1669
    tv.tv_usec = 0;
 
1670
    file_ctx->timer = tevent_add_timer(ev, file_ctx->parent_ctx, tv,
 
1671
                             poll_config_file, file_ctx);
 
1672
    if (!file_ctx->timer) {
 
1673
        DEBUG(0, ("Error: Config file no longer monitored for changes!\n"));
 
1674
    }
 
1675
}
 
1676
 
 
1677
static int try_inotify(struct config_file_ctx *file_ctx, const char *filename,
 
1678
                       monitor_reconf_fn fn)
 
1679
{
 
1680
#ifdef HAVE_SYS_INOTIFY_H
 
1681
    int err, fd_args, ret;
 
1682
    struct tevent_fd *tfd;
 
1683
    struct config_file_callback *cb;
 
1684
 
 
1685
    /* Monitoring the file descriptor should be global */
 
1686
    if (!file_ctx->mt_ctx->inotify_fd) {
 
1687
        /* Set up inotify to monitor the config file for changes */
 
1688
        file_ctx->mt_ctx->inotify_fd = inotify_init();
 
1689
        if (file_ctx->mt_ctx->inotify_fd < 0) {
 
1690
            err = errno;
 
1691
            DEBUG(0, ("Could not initialize inotify, error [%d:%s]\n",
 
1692
                      err, strerror(err)));
 
1693
            return err;
 
1694
        }
 
1695
 
 
1696
        fd_args = fcntl(file_ctx->mt_ctx->inotify_fd, F_GETFL, NULL);
 
1697
        if (fd_args < 0) {
 
1698
            /* Could not set nonblocking */
 
1699
            close(file_ctx->mt_ctx->inotify_fd);
 
1700
            return EINVAL;
 
1701
        }
 
1702
 
 
1703
        fd_args |= O_NONBLOCK;
 
1704
        ret = fcntl(file_ctx->mt_ctx->inotify_fd, F_SETFL, fd_args);
 
1705
        if (ret < 0) {
 
1706
            /* Could not set nonblocking */
 
1707
            close(file_ctx->mt_ctx->inotify_fd);
 
1708
            return EINVAL;
 
1709
        }
 
1710
 
 
1711
        /* Add the inotify file descriptor to the TEvent context */
 
1712
        tfd = tevent_add_fd(file_ctx->mt_ctx->ev, file_ctx,
 
1713
                            file_ctx->mt_ctx->inotify_fd,
 
1714
                            TEVENT_FD_READ, config_file_changed,
 
1715
                            file_ctx);
 
1716
        if (!tfd) {
 
1717
            close(file_ctx->mt_ctx->inotify_fd);
 
1718
            return EIO;
 
1719
        }
 
1720
    }
 
1721
 
 
1722
    cb = talloc_zero(file_ctx, struct config_file_callback);
 
1723
    if(!cb) {
 
1724
        close(file_ctx->mt_ctx->inotify_fd);
 
1725
        return EIO;
 
1726
    }
 
1727
 
 
1728
    cb->filename = talloc_strdup(cb, filename);
 
1729
    if (!cb->filename) {
 
1730
        close(file_ctx->mt_ctx->inotify_fd);
 
1731
        return ENOMEM;
 
1732
    }
 
1733
    cb->wd = inotify_add_watch(file_ctx->mt_ctx->inotify_fd,
 
1734
                               cb->filename, IN_MODIFY);
 
1735
    if (cb->wd < 0) {
 
1736
        err = errno;
 
1737
        DEBUG(0, ("Could not add inotify watch for file [%s]. Error [%d:%s]\n",
 
1738
                  cb->filename, err, strerror(err)));
 
1739
        close(file_ctx->mt_ctx->inotify_fd);
 
1740
        return err;
 
1741
    }
 
1742
    cb->fn = fn;
 
1743
 
 
1744
    DLIST_ADD(file_ctx->callbacks, cb);
 
1745
 
 
1746
    return EOK;
 
1747
#else
 
1748
    return EINVAL;
 
1749
#endif
 
1750
}
 
1751
 
 
1752
static int monitor_config_file(TALLOC_CTX *mem_ctx,
 
1753
                               struct mt_ctx *ctx,
 
1754
                               const char *file,
 
1755
                               monitor_reconf_fn fn)
 
1756
{
 
1757
    int ret, err;
 
1758
    bool use_inotify;
 
1759
    struct timeval tv;
 
1760
    struct stat file_stat;
 
1761
    struct config_file_callback *cb = NULL;
 
1762
 
 
1763
    ret = stat(file, &file_stat);
 
1764
    if (ret < 0) {
 
1765
        err = errno;
 
1766
        DEBUG(0, ("Could not stat file [%s]. Error [%d:%s]\n",
 
1767
                  file, err, strerror(err)));
 
1768
        return err;
 
1769
    }
 
1770
    if (!ctx->file_ctx) {
 
1771
        ctx->file_ctx = talloc_zero(mem_ctx, struct config_file_ctx);
 
1772
        if (!ctx->file_ctx) return ENOMEM;
 
1773
 
 
1774
        ctx->file_ctx->parent_ctx = mem_ctx;
 
1775
        ctx->file_ctx->mt_ctx = ctx;
 
1776
    }
 
1777
 
 
1778
    ret = confdb_get_bool(ctx->cdb, ctx,
 
1779
                          CONFDB_MONITOR_CONF_ENTRY,
 
1780
                          CONFDB_MONITOR_TRY_INOTIFY,
 
1781
                          true, &use_inotify);
 
1782
    if (ret != EOK) {
 
1783
        talloc_free(ctx->file_ctx);
 
1784
        return ret;
 
1785
    }
 
1786
 
 
1787
    if (use_inotify) {
 
1788
        ret = try_inotify(ctx->file_ctx, file, fn);
 
1789
        if (ret != EOK) {
 
1790
            use_inotify = false;
 
1791
        }
 
1792
    }
 
1793
 
 
1794
    if (!use_inotify) {
 
1795
        /* Could not monitor file with inotify, fall back to polling */
 
1796
        cb = talloc_zero(ctx->file_ctx, struct config_file_callback);
 
1797
        if (!cb) {
 
1798
            talloc_free(ctx->file_ctx);
 
1799
            return ENOMEM;
 
1800
        }
 
1801
        cb->filename = talloc_strdup(cb, file);
 
1802
        if (!cb->filename) {
 
1803
            talloc_free(ctx->file_ctx);
 
1804
            return ENOMEM;
 
1805
        }
 
1806
        cb->fn = fn;
 
1807
        cb->modified = file_stat.st_mtime;
 
1808
 
 
1809
        DLIST_ADD(ctx->file_ctx->callbacks, cb);
 
1810
 
 
1811
        if(!ctx->file_ctx->timer) {
 
1812
            gettimeofday(&tv, NULL);
 
1813
            tv.tv_sec += CONFIG_FILE_POLL_INTERVAL;
 
1814
            tv.tv_usec = 0;
 
1815
            ctx->file_ctx->timer = tevent_add_timer(ctx->ev, mem_ctx, tv,
 
1816
                                   poll_config_file, ctx->file_ctx);
 
1817
            if (!ctx->file_ctx->timer) {
 
1818
                talloc_free(ctx->file_ctx);
 
1819
                return EIO;
 
1820
            }
 
1821
        }
 
1822
    }
 
1823
 
 
1824
    return EOK;
 
1825
}
 
1826
 
 
1827
int monitor_process_init(struct mt_ctx *ctx,
 
1828
                         const char *config_file)
 
1829
{
 
1830
    TALLOC_CTX *tmp_ctx;
 
1831
    struct sysdb_ctx_list *db_list;
 
1832
    struct tevent_signal *tes;
 
1833
    struct sss_domain_info *dom;
 
1834
    int num_providers;
 
1835
    int ret;
 
1836
 
 
1837
    /* Set up an event handler for a SIGHUP */
 
1838
    tes = tevent_add_signal(ctx->ev, ctx, SIGHUP, 0,
 
1839
                            monitor_hup, ctx);
 
1840
    if (tes == NULL) {
 
1841
        return EIO;
 
1842
    }
 
1843
 
 
1844
    /* Set up an event handler for a SIGINT */
 
1845
    BlockSignals(false, SIGINT);
 
1846
    tes = tevent_add_signal(ctx->ev, ctx, SIGINT, 0,
 
1847
                            monitor_quit, ctx);
 
1848
    if (tes == NULL) {
 
1849
        return EIO;
 
1850
    }
 
1851
 
 
1852
    /* Set up an event handler for a SIGTERM */
 
1853
    tes = tevent_add_signal(ctx->ev, ctx, SIGTERM, 0,
 
1854
                            monitor_quit, ctx);
 
1855
    if (tes == NULL) {
 
1856
        return EIO;
 
1857
    }
 
1858
 
 
1859
    /* Handle SIGUSR1 (tell all providers to go offline) */
 
1860
    BlockSignals(false, SIGUSR1);
 
1861
    tes = tevent_add_signal(ctx->ev, ctx, SIGUSR1, 0,
 
1862
                            signal_offline, ctx);
 
1863
    if (tes == NULL) {
 
1864
        return EIO;
 
1865
    }
 
1866
 
 
1867
    /* Handle SIGUSR2 (tell all providers to go reset offline) */
 
1868
    BlockSignals(false, SIGUSR2);
 
1869
    tes = tevent_add_signal(ctx->ev, ctx, SIGUSR2, 0,
 
1870
                            signal_offline_reset, ctx);
 
1871
    if (tes == NULL) {
 
1872
        return EIO;
 
1873
    }
 
1874
 
 
1875
#if 0
 
1876
    This feature is incomplete and can leave the SSSD in a bad state if the
 
1877
    config file is changed while the SSSD is running.
 
1878
 
 
1879
    Uncomment this once the backends are honoring reloadConfig()
 
1880
 
 
1881
    /* Watch for changes to the confdb config file */
 
1882
    ret = monitor_config_file(ctx, ctx, config_file, monitor_signal_reconf);
 
1883
    if (ret != EOK) {
 
1884
        return ret;
 
1885
    }
 
1886
#endif
 
1887
    /* Watch for changes to the DNS resolv.conf */
 
1888
    ret = monitor_config_file(ctx, ctx, RESOLV_CONF_PATH,
 
1889
                              monitor_update_resolv);
 
1890
    if (ret != EOK) {
 
1891
        return ret;
 
1892
    }
 
1893
 
 
1894
    /* Avoid a startup race condition between process.
 
1895
     * We need to handle DB upgrades or DB creation only
 
1896
     * in one process before all other start.
 
1897
     */
 
1898
    tmp_ctx = talloc_new(NULL);
 
1899
    if (!tmp_ctx) {
 
1900
        return ENOMEM;
 
1901
    }
 
1902
    ret = sysdb_init(tmp_ctx, ctx->cdb, NULL, true, &db_list);
 
1903
    if (ret != EOK) {
 
1904
        return ret;
 
1905
    }
 
1906
    talloc_zfree(tmp_ctx);
 
1907
 
 
1908
    /* Initialize D-BUS Server
 
1909
     * The monitor will act as a D-BUS server for all
 
1910
     * SSSD processes */
 
1911
    ret = monitor_dbus_init(ctx);
 
1912
    if (ret != EOK) {
 
1913
        return ret;
 
1914
    }
 
1915
 
 
1916
    ret = setup_netlink(ctx, ctx->ev, network_status_change_cb,
 
1917
                        ctx, &ctx->nlctx);
 
1918
    if (ret != EOK) {
 
1919
        DEBUG(2, ("Cannot set up listening for network notifications\n"));
 
1920
        return ret;
 
1921
    }
 
1922
 
 
1923
    /* start providers */
 
1924
    num_providers = 0;
 
1925
    for (dom = ctx->domains; dom; dom = dom->next) {
 
1926
        ret = add_new_provider(ctx, dom->name);
 
1927
        if (ret != EOK && ret != ENOENT) {
 
1928
            return ret;
 
1929
        }
 
1930
        if (ret != ENOENT) {
 
1931
            num_providers++;
 
1932
        }
 
1933
    }
 
1934
 
 
1935
    if (num_providers > 0) {
 
1936
        /* now set the services stratup timeout *
 
1937
         * (responders will be started automatically when all
 
1938
         *  providers are up and running or when the tomeout
 
1939
         *  expires) */
 
1940
        ret = add_services_startup_timeout(ctx);
 
1941
        if (ret != EOK) {
 
1942
            return ret;
 
1943
        }
 
1944
    } else {
 
1945
        int i;
 
1946
 
 
1947
        ctx->services_started = true;
 
1948
 
 
1949
        /* No providers start services immediately
 
1950
         * Normally this means only LOCAL is configured */
 
1951
        for (i = 0; ctx->services[i]; i++) {
 
1952
            add_new_service(ctx, ctx->services[i]);
 
1953
        }
 
1954
    }
 
1955
 
 
1956
    /* now start checking for global events */
 
1957
    set_global_checker(ctx);
 
1958
 
 
1959
    return EOK;
 
1960
}
 
1961
 
 
1962
static void init_timeout(struct tevent_context *ev,
 
1963
                         struct tevent_timer *te,
 
1964
                         struct timeval t, void *ptr)
 
1965
{
 
1966
    struct mon_init_conn *mini;
 
1967
 
 
1968
    DEBUG(2, ("Client timed out before Identification!\n"));
 
1969
 
 
1970
    mini = talloc_get_type(ptr, struct mon_init_conn);
 
1971
 
 
1972
    sbus_disconnect(mini->conn);
 
1973
    talloc_zfree(mini);
 
1974
}
 
1975
 
 
1976
/*
 
1977
 * monitor_service_init
 
1978
 * Set up a timeout function and temporary connection structure.
 
1979
 * If the client does not identify before the timeout kicks in,
 
1980
 * the client is forcibly disconnected.
 
1981
 */
 
1982
static int monitor_service_init(struct sbus_connection *conn, void *data)
 
1983
{
 
1984
    struct mt_ctx *ctx;
 
1985
    struct mon_init_conn *mini;
 
1986
    struct timeval tv;
 
1987
 
 
1988
    DEBUG(3, ("Initializing D-BUS Service\n"));
 
1989
 
 
1990
    ctx = talloc_get_type(data, struct mt_ctx);
 
1991
 
 
1992
    mini = talloc(conn, struct mon_init_conn);
 
1993
    if (!mini) {
 
1994
        DEBUG(0,("Out of memory?!\n"));
 
1995
        talloc_zfree(conn);
 
1996
        return ENOMEM;
 
1997
    }
 
1998
    mini->ctx = ctx;
 
1999
    mini->conn = conn;
 
2000
 
 
2001
    /* 5 seconds should be plenty */
 
2002
    tv = tevent_timeval_current_ofs(10, 0);
 
2003
 
 
2004
    mini->timeout = tevent_add_timer(ctx->ev, mini, tv, init_timeout, mini);
 
2005
    if (!mini->timeout) {
 
2006
        DEBUG(0,("Out of memory?!\n"));
 
2007
        talloc_zfree(conn);
 
2008
        return ENOMEM;
 
2009
    }
 
2010
 
 
2011
    sbus_conn_set_private_data(conn, mini);
 
2012
 
 
2013
    return EOK;
 
2014
}
 
2015
 
 
2016
/* service_send_ping
 
2017
 * this function send a dbus ping to a service.
 
2018
 * It returns EOK if all is fine or ENXIO if the connection is
 
2019
 * not available (either not yet set up or teared down).
 
2020
 * Returns e generic error in other cases.
 
2021
 */
 
2022
static int service_send_ping(struct mt_svc *svc)
 
2023
{
 
2024
    DBusMessage *msg;
 
2025
    int ret;
 
2026
 
 
2027
    if (!svc->conn) {
 
2028
        DEBUG(8, ("Service not yet initialized\n"));
 
2029
        return ENXIO;
 
2030
    }
 
2031
 
 
2032
    DEBUG(4,("Pinging %s\n", svc->name));
 
2033
 
 
2034
    /*
 
2035
     * Set up identity request
 
2036
     * This should be a well-known path and method
 
2037
     * for all services
 
2038
     */
 
2039
    msg = dbus_message_new_method_call(NULL,
 
2040
                                       MONITOR_PATH,
 
2041
                                       MONITOR_INTERFACE,
 
2042
                                       MON_CLI_METHOD_PING);
 
2043
    if (!msg) {
 
2044
        DEBUG(0,("Out of memory?!\n"));
 
2045
        talloc_zfree(svc->conn);
 
2046
        return ENOMEM;
 
2047
    }
 
2048
 
 
2049
    ret = sbus_conn_send(svc->conn, msg,
 
2050
                         svc->mt_ctx->service_id_timeout,
 
2051
                         ping_check, svc, NULL);
 
2052
    dbus_message_unref(msg);
 
2053
    return ret;
 
2054
}
 
2055
 
 
2056
static void ping_check(DBusPendingCall *pending, void *data)
 
2057
{
 
2058
    struct mt_svc *svc;
 
2059
    DBusMessage *reply;
 
2060
    const char *dbus_error_name;
 
2061
    int type;
 
2062
 
 
2063
    svc = talloc_get_type(data, struct mt_svc);
 
2064
 
 
2065
    reply = dbus_pending_call_steal_reply(pending);
 
2066
    if (!reply) {
 
2067
        /* reply should never be null. This function shouldn't be called
 
2068
         * until reply is valid or timeout has occurred. If reply is NULL
 
2069
         * here, something is seriously wrong and we should bail out.
 
2070
         */
 
2071
        DEBUG(0, ("A reply callback was called but no reply was received"
 
2072
                  " and no timeout occurred\n"));
 
2073
 
 
2074
        /* Destroy this connection */
 
2075
        sbus_disconnect(svc->conn);
 
2076
        goto done;
 
2077
    }
 
2078
 
 
2079
    type = dbus_message_get_type(reply);
 
2080
    switch (type) {
 
2081
    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
 
2082
        /* ok peer replied,
 
2083
         * make sure we reset the failure counter in the service structure */
 
2084
 
 
2085
        DEBUG(4,("Service %s replied to ping\n", svc->name));
 
2086
 
 
2087
        svc->failed_pongs = 0;
 
2088
        break;
 
2089
 
 
2090
    case DBUS_MESSAGE_TYPE_ERROR:
 
2091
 
 
2092
        dbus_error_name = dbus_message_get_error_name(reply);
 
2093
 
 
2094
        /* timeouts are handled in the main service check function */
 
2095
        if (strcmp(dbus_error_name, DBUS_ERROR_TIMEOUT) == 0)
 
2096
            break;
 
2097
 
 
2098
        DEBUG(0,("A service PING returned an error [%s], closing connection.\n",
 
2099
                 dbus_error_name));
 
2100
        /* Falling through to default intentionally*/
 
2101
    default:
 
2102
        /*
 
2103
         * Timeout or other error occurred or something
 
2104
         * unexpected happened.
 
2105
         * It doesn't matter which, because either way we
 
2106
         * know that this connection isn't trustworthy.
 
2107
         * We'll destroy it now.
 
2108
         */
 
2109
        sbus_disconnect(svc->conn);
 
2110
    }
 
2111
 
 
2112
done:
 
2113
    dbus_pending_call_unref(pending);
 
2114
    dbus_message_unref(reply);
 
2115
}
 
2116
 
 
2117
 
 
2118
 
 
2119
/* service_check_alive
 
2120
 * This function checks if the service child is still alive
 
2121
 */
 
2122
static int service_check_alive(struct mt_svc *svc)
 
2123
{
 
2124
    int status;
 
2125
    pid_t pid;
 
2126
 
 
2127
    DEBUG(4,("Checking service %s(%d) is still alive\n", svc->name, svc->pid));
 
2128
 
 
2129
    pid = waitpid(svc->pid, &status, WNOHANG);
 
2130
    if (pid == 0) {
 
2131
        return EOK;
 
2132
    }
 
2133
 
 
2134
    if (pid != svc->pid) {
 
2135
        DEBUG(1, ("bad return (%d) from waitpid() waiting for %d\n",
 
2136
                  pid, svc->pid));
 
2137
        /* TODO: what do we do now ? */
 
2138
        return EINVAL;
 
2139
    }
 
2140
 
 
2141
    if (WIFEXITED(status)) { /* children exited on it's own */
 
2142
        /* TODO: check configuration to see if it was removed
 
2143
         * from the list of process to run */
 
2144
        DEBUG(0,("Process [%s] exited\n", svc->name));
 
2145
    }
 
2146
 
 
2147
    return ECHILD;
 
2148
}
 
2149
 
 
2150
static void service_startup_handler(struct tevent_context *ev,
 
2151
                                    struct tevent_timer *te,
 
2152
                                    struct timeval t, void *ptr);
 
2153
 
 
2154
static int start_service(struct mt_svc *svc)
 
2155
{
 
2156
    struct tevent_timer *te;
 
2157
    struct timeval tv;
 
2158
 
 
2159
    DEBUG(4,("Queueing service %s for startup\n", svc->name));
 
2160
 
 
2161
    /* at startup we need to start the data providers before the responders
 
2162
     * to avoid races where a service starts before sbus pipes are ready
 
2163
     * to accept connections. So if startup is true delay by 2 seconds any
 
2164
     * process that is not a data provider */
 
2165
 
 
2166
    tv = tevent_timeval_current();
 
2167
 
 
2168
    /* Add a timed event to start up the service.
 
2169
     * We have to do this in order to avoid a race
 
2170
     * condition where the service being started forks
 
2171
     * and attempts to connect to the SBUS before
 
2172
     * the monitor is serving it.
 
2173
     */
 
2174
    te = tevent_add_timer(svc->mt_ctx->ev, svc, tv,
 
2175
                          service_startup_handler, svc);
 
2176
    if (te == NULL) {
 
2177
        DEBUG(0, ("Unable to queue service %s for startup\n", svc->name));
 
2178
        return ENOMEM;
 
2179
    }
 
2180
    return EOK;
 
2181
}
 
2182
 
 
2183
static void service_startup_handler(struct tevent_context *ev,
 
2184
                                    struct tevent_timer *te,
 
2185
                                    struct timeval t, void *ptr)
 
2186
{
 
2187
    struct mt_svc *mt_svc;
 
2188
    char **args;
 
2189
 
 
2190
    mt_svc = talloc_get_type(ptr, struct mt_svc);
 
2191
    if (mt_svc == NULL) {
 
2192
        return;
 
2193
    }
 
2194
 
 
2195
    mt_svc->pid = fork();
 
2196
    if (mt_svc->pid != 0) {
 
2197
        if (mt_svc->pid == -1) {
 
2198
            DEBUG(0, ("Could not fork child to start service [%s]. Continuing.\n", mt_svc->name))
 
2199
            return;
 
2200
        }
 
2201
 
 
2202
        /* Parent */
 
2203
        mt_svc->mt_ctx->check_children = true;
 
2204
        mt_svc->failed_pongs = 0;
 
2205
        DLIST_ADD(mt_svc->mt_ctx->svc_list, mt_svc);
 
2206
        set_tasks_checker(mt_svc);
 
2207
 
 
2208
        return;
 
2209
    }
 
2210
 
 
2211
    /* child */
 
2212
 
 
2213
    args = parse_args(mt_svc->command);
 
2214
    execvp(args[0], args);
 
2215
 
 
2216
    /* If we are here, exec() has failed
 
2217
     * Print errno and abort quickly */
 
2218
    DEBUG(0,("Could not exec %s, reason: %s\n", mt_svc->command, strerror(errno)));
 
2219
 
 
2220
    /* We have to call _exit() instead of exit() here
 
2221
     * because a bug in D-BUS will cause the server to
 
2222
     * close its socket at exit() */
 
2223
    _exit(1);
 
2224
}
 
2225
 
 
2226
int main(int argc, const char *argv[])
 
2227
{
 
2228
    int opt;
 
2229
    poptContext pc;
 
2230
    int opt_daemon = 0;
 
2231
    int opt_interactive = 0;
 
2232
    char *opt_config_file = NULL;
 
2233
    char *config_file = NULL;
 
2234
    int flags = 0;
 
2235
    struct main_context *main_ctx;
 
2236
    TALLOC_CTX *tmp_ctx;
 
2237
    struct mt_ctx *monitor;
 
2238
    int ret;
 
2239
    uid_t uid;
 
2240
 
 
2241
    struct poptOption long_options[] = {
 
2242
        POPT_AUTOHELP
 
2243
        SSSD_MAIN_OPTS
 
2244
        {"daemon", 'D', POPT_ARG_NONE, &opt_daemon, 0, \
 
2245
         _("Become a daemon (default)"), NULL }, \
 
2246
        {"interactive", 'i', POPT_ARG_NONE, &opt_interactive, 0, \
 
2247
         _("Run interactive (not a daemon)"), NULL}, \
 
2248
        {"config", 'c', POPT_ARG_STRING, &opt_config_file, 0, \
 
2249
         _("Specify a non-default config file"), NULL}, \
 
2250
        POPT_TABLEEND
 
2251
    };
 
2252
 
 
2253
    pc = poptGetContext(argv[0], argc, argv, long_options, 0);
 
2254
    while((opt = poptGetNextOpt(pc)) != -1) {
 
2255
        switch(opt) {
 
2256
        default:
 
2257
            fprintf(stderr, "\nInvalid option %s: %s\n\n",
 
2258
                    poptBadOption(pc, 0), poptStrerror(opt));
 
2259
            poptPrintUsage(pc, stderr, 0);
 
2260
            return 1;
 
2261
        }
 
2262
    }
 
2263
 
 
2264
    if (opt_daemon && opt_interactive) {
 
2265
        fprintf(stderr, "Option -i|--interactive is not allowed together with -D|--daemon\n");
 
2266
        poptPrintUsage(pc, stderr, 0);
 
2267
        return 1;
 
2268
    }
 
2269
 
 
2270
    if (!opt_daemon && !opt_interactive) {
 
2271
        opt_daemon = 1;
 
2272
    }
 
2273
 
 
2274
    poptFreeContext(pc);
 
2275
 
 
2276
    uid = getuid();
 
2277
    if (uid != 0) {
 
2278
        DEBUG(1, ("Running under %d, must be root\n", uid));
 
2279
        sss_log(SSS_LOG_ALERT, "sssd must be run as root");
 
2280
        return 8;
 
2281
    }
 
2282
 
 
2283
    tmp_ctx = talloc_new(NULL);
 
2284
    if (!tmp_ctx) {
 
2285
        return 7;
 
2286
    }
 
2287
 
 
2288
    if (opt_daemon) flags |= FLAGS_DAEMON;
 
2289
    if (opt_interactive) flags |= FLAGS_INTERACTIVE;
 
2290
 
 
2291
    if (opt_config_file)
 
2292
        config_file = talloc_strdup(tmp_ctx, opt_config_file);
 
2293
    else
 
2294
        config_file = talloc_strdup(tmp_ctx, CONFDB_DEFAULT_CONFIG_FILE);
 
2295
    if(!config_file)
 
2296
        return 6;
 
2297
 
 
2298
    /* we want a pid file check */
 
2299
    flags |= FLAGS_PID_FILE;
 
2300
 
 
2301
    /* Open before server_setup() does to have logging
 
2302
     * during configuration checking */
 
2303
    if (debug_to_file) {
 
2304
        ret = open_debug_file();
 
2305
        if (ret) {
 
2306
            return 7;
 
2307
        }
 
2308
    }
 
2309
 
 
2310
    /* Warn if nscd seems to be running */
 
2311
    ret = check_file(NSCD_SOCKET_PATH, -1, -1, -1, CHECK_SOCK, NULL);
 
2312
    if (ret == EOK) {
 
2313
        sss_log(SSS_LOG_NOTICE,
 
2314
                "nscd socket was detected.  Nscd caching capabilities "
 
2315
                "may conflict with SSSD for users and groups. It is "
 
2316
                "recommended not to run nscd in parallel with SSSD, unless "
 
2317
                "nscd is configured not to cache the passwd, group and "
 
2318
                "netgroup nsswitch maps.");
 
2319
    }
 
2320
 
 
2321
    /* Parse config file, fail if cannot be done */
 
2322
    ret = load_configuration(tmp_ctx, config_file, &monitor);
 
2323
    if (ret != EOK) {
 
2324
        if (ret == EPERM) {
 
2325
            DEBUG(1, ("Cannot read configuration file %s\n", config_file));
 
2326
            sss_log(SSS_LOG_ALERT,
 
2327
                    "Cannot read config file %s, please check if permissions "
 
2328
                    "are 0600 and the file is owned by root.root", config_file);
 
2329
        } else {
 
2330
            DEBUG(1, ("Error loading configuration database: [%d]: %s",
 
2331
                      ret, strerror(ret)));
 
2332
            sss_log(SSS_LOG_ALERT, "Cannot load configuration database");
 
2333
        }
 
2334
        return 4;
 
2335
    }
 
2336
 
 
2337
    /* set up things like debug , signals, daemonization, etc... */
 
2338
    ret = server_setup("sssd", flags, CONFDB_MONITOR_CONF_ENTRY, &main_ctx);
 
2339
    if (ret != EOK) return 2;
 
2340
 
 
2341
    monitor->ev = main_ctx->event_ctx;
 
2342
    talloc_steal(main_ctx, monitor);
 
2343
 
 
2344
    ret = monitor_process_init(monitor,
 
2345
                               config_file);
 
2346
    if (ret != EOK) return 3;
 
2347
    talloc_free(tmp_ctx);
 
2348
 
 
2349
    /* loop on main */
 
2350
    server_loop(main_ctx);
 
2351
 
 
2352
    ret = monitor_cleanup();
 
2353
    if (ret != EOK) return 5;
 
2354
 
 
2355
    return 0;
 
2356
}