~ubuntu-branches/ubuntu/karmic/sssd/karmic

« back to all changes in this revision

Viewing changes to server/confdb/confdb.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2009-08-24 16:35:11 UTC
  • Revision ID: james.westby@ubuntu.com-20090824163511-l20qd53jlb0bv56d
Tags: upstream-0.5.0
ImportĀ upstreamĀ versionĀ 0.5.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   SSSD
 
3
 
 
4
   NSS Configuratoin DB
 
5
 
 
6
   Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
 
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
 
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#define _GNU_SOURCE
 
23
 
 
24
#include "config.h"
 
25
#include "util/util.h"
 
26
#include "confdb/confdb.h"
 
27
#include "confdb/confdb_private.h"
 
28
#include "util/btreemap.h"
 
29
#include "db/sysdb.h"
 
30
 
 
31
#define CONFDB_DOMAINS_PATH "config/domains"
 
32
#define CONFDB_DOMAIN_BASEDN "cn=domains,cn=config"
 
33
#define CONFDB_DOMAIN_ATTR "cn"
 
34
#define CONFDB_MPG "magicPrivateGroups"
 
35
#define CONFDB_FQ "useFullyQualifiedNames"
 
36
 
 
37
#define CONFDB_ZERO_CHECK_OR_JUMP(var, ret, err, label) do { \
 
38
    if (!var) { \
 
39
        ret = err; \
 
40
        goto label; \
 
41
    } \
 
42
} while(0)
 
43
 
 
44
static char *prepend_cn(char *str, int *slen, const char *comp, int clen)
 
45
{
 
46
    char *ret;
 
47
 
 
48
    ret = talloc_realloc(NULL, str, char, *slen + 4 + clen + 1);
 
49
    if (!ret)
 
50
        return NULL;
 
51
 
 
52
    /* move current string to the end */
 
53
    memmove(&ret[clen +4], ret, *slen+1); /* includes termination */
 
54
    memcpy(ret, "cn=", 3);
 
55
    memcpy(&ret[3], comp, clen);
 
56
    ret[clen+3] = ',';
 
57
 
 
58
    *slen = *slen + 4 + clen;
 
59
 
 
60
    return ret;
 
61
}
 
62
 
 
63
int parse_section(TALLOC_CTX *mem_ctx, const char *section,
 
64
                  char **sec_dn, const char **rdn_name)
 
65
{
 
66
    TALLOC_CTX *tmp_ctx;
 
67
    char *dn = NULL;
 
68
    char *p;
 
69
    const char *s;
 
70
    int l, ret;
 
71
 
 
72
    /* section must be a non null string and must not start with '/' */
 
73
    if (!section || !*section || *section == '/') return EINVAL;
 
74
 
 
75
    tmp_ctx = talloc_new(mem_ctx);
 
76
    if (!tmp_ctx) return ENOMEM;
 
77
 
 
78
    s = section;
 
79
    l = 0;
 
80
    while ((p = strchrnul(s, '/'))) {
 
81
        if (l == 0) {
 
82
            dn = talloc_asprintf(tmp_ctx, "cn=%s", s);
 
83
            l = 3 + (p-s);
 
84
            dn[l] = '\0';
 
85
        } else {
 
86
            dn = prepend_cn(dn, &l, s, p-s);
 
87
        }
 
88
        if (!dn) {
 
89
            ret = ENOMEM;
 
90
            goto done;
 
91
        }
 
92
        if (*p == '\0') {
 
93
            if (rdn_name) *rdn_name = s;
 
94
            break; /* reached end */
 
95
        }
 
96
        s = p+1;
 
97
        if (*s == '\0') { /* a section cannot end in '.' */
 
98
            ret = EINVAL;
 
99
            goto done;
 
100
        }
 
101
    }
 
102
 
 
103
    *sec_dn = talloc_steal(mem_ctx, dn);
 
104
    ret = EOK;
 
105
 
 
106
done:
 
107
    talloc_free(tmp_ctx);
 
108
    return ret;
 
109
}
 
110
 
 
111
/* split a string into an allocated array of strings.
 
112
 * the separator is a string, and is case-sensitive.
 
113
 * optionally single values can be trimmed of of spaces and tabs */
 
114
static int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
 
115
                              const char *sep, bool trim, char ***_list, int *size)
 
116
{
 
117
    const char *t, *p, *n;
 
118
    size_t l, s, len;
 
119
    char **list, **r;
 
120
 
 
121
    if (!str || !*str || !sep || !*sep || !_list) return EINVAL;
 
122
 
 
123
    s = strlen(sep);
 
124
    t = str;
 
125
 
 
126
    list = NULL;
 
127
    l = 0;
 
128
 
 
129
    if (trim)
 
130
        while (*t == ' ' || *t == '\t') t++;
 
131
 
 
132
    while (t && (p = strstr(t, sep))) {
 
133
        len = p - t;
 
134
        n = p + s; /* save next string starting point */
 
135
        if (trim) {
 
136
            while (*t == ' ' || *t == '\t') {
 
137
                t++;
 
138
                len--;
 
139
                if (len == 0) break;
 
140
            }
 
141
            p--;
 
142
            while (len > 0 && (*p == ' ' || *p == '\t')) {
 
143
                len--;
 
144
                p--;
 
145
            }
 
146
        }
 
147
 
 
148
        r = talloc_realloc(mem_ctx, list, char *, l + 2);
 
149
        if (!r) {
 
150
            talloc_free(list);
 
151
            return ENOMEM;
 
152
        } else {
 
153
            list = r;
 
154
        }
 
155
 
 
156
        if (len == 0) {
 
157
            list[l] = talloc_strdup(list, "");
 
158
        } else {
 
159
            list[l] = talloc_strndup(list, t, len);
 
160
        }
 
161
        if (!list[l]) {
 
162
            talloc_free(list);
 
163
            return ENOMEM;
 
164
        }
 
165
        l++;
 
166
 
 
167
        t = n; /* move to next string */
 
168
    }
 
169
 
 
170
    if (t) {
 
171
        r = talloc_realloc(mem_ctx, list, char *, l + 2);
 
172
        if (!r) {
 
173
            talloc_free(list);
 
174
            return ENOMEM;
 
175
        } else {
 
176
            list = r;
 
177
        }
 
178
 
 
179
        if (trim) {
 
180
            len = strlen(t);
 
181
            while (*t == ' ' || *t == '\t') {
 
182
                t++;
 
183
                len--;
 
184
                if (len == 0) break;
 
185
            }
 
186
            p = t + len - 1;
 
187
            while (len > 0 && (*p == ' ' || *p == '\t')) {
 
188
                len--;
 
189
                p--;
 
190
            }
 
191
 
 
192
            if (len == 0) {
 
193
                list[l] = talloc_strdup(list, "");
 
194
            } else {
 
195
                list[l] = talloc_strndup(list, t, len);
 
196
            }
 
197
        } else {
 
198
            list[l] = talloc_strdup(list, t);
 
199
        }
 
200
        if (!list[l]) {
 
201
            talloc_free(list);
 
202
            return ENOMEM;
 
203
        }
 
204
        l++;
 
205
    }
 
206
 
 
207
    list[l] = NULL; /* terminate list */
 
208
 
 
209
    if (size) *size = l + 1;
 
210
    *_list = list;
 
211
 
 
212
    return EOK;
 
213
}
 
214
 
 
215
int confdb_add_param(struct confdb_ctx *cdb,
 
216
                     bool replace,
 
217
                     const char *section,
 
218
                     const char *attribute,
 
219
                     const char **values)
 
220
{
 
221
    TALLOC_CTX *tmp_ctx = NULL;
 
222
    struct ldb_message *msg;
 
223
    struct ldb_result *res;
 
224
    struct ldb_dn *dn;
 
225
    char *secdn;
 
226
    const char *rdn_name;
 
227
    int ret, i;
 
228
 
 
229
    tmp_ctx = talloc_new(NULL);
 
230
    if (!tmp_ctx) {
 
231
        ret = ENOMEM;
 
232
        goto done;
 
233
    }
 
234
 
 
235
    ret = parse_section(tmp_ctx, section, &secdn, &rdn_name);
 
236
    if (ret != EOK) {
 
237
        goto done;
 
238
    }
 
239
 
 
240
    dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
 
241
    CONFDB_ZERO_CHECK_OR_JUMP(dn, ret, EIO, done);
 
242
 
 
243
    ret = ldb_search(cdb->ldb, tmp_ctx, &res,
 
244
                     dn, LDB_SCOPE_BASE, NULL, NULL);
 
245
    if (ret != LDB_SUCCESS) {
 
246
        ret = EIO;
 
247
        goto done;
 
248
    }
 
249
 
 
250
    msg = ldb_msg_new(tmp_ctx);
 
251
    CONFDB_ZERO_CHECK_OR_JUMP(msg, ret, ENOMEM, done);
 
252
 
 
253
    msg->dn = talloc_steal(msg, dn);
 
254
    CONFDB_ZERO_CHECK_OR_JUMP(msg->dn, ret, ENOMEM, done);
 
255
 
 
256
    if (res->count == 0) { /* add a new message */
 
257
        errno = 0;
 
258
 
 
259
        /* cn first */
 
260
        ret = ldb_msg_add_string(msg, "cn", rdn_name);
 
261
        if (ret != LDB_SUCCESS) {
 
262
            if (errno) ret = errno;
 
263
            else ret = EIO;
 
264
            goto done;
 
265
        }
 
266
 
 
267
        /* now the requested attribute */
 
268
        for (i = 0; values[i]; i++) {
 
269
            ret = ldb_msg_add_string(msg, attribute, values[i]);
 
270
            if (ret != LDB_SUCCESS) {
 
271
                if (errno) ret = errno;
 
272
                else ret = EIO;
 
273
                goto done;
 
274
            }
 
275
        }
 
276
 
 
277
        ret = ldb_add(cdb->ldb, msg);
 
278
        if (ret != LDB_SUCCESS) {
 
279
            ret = EIO;
 
280
            goto done;
 
281
        }
 
282
 
 
283
    } else {
 
284
        int optype;
 
285
        errno = 0;
 
286
 
 
287
        /* mark this as a replacement */
 
288
        if (replace) optype = LDB_FLAG_MOD_REPLACE;
 
289
        else optype = LDB_FLAG_MOD_ADD;
 
290
        ret = ldb_msg_add_empty(msg, attribute, optype, NULL);
 
291
        if (ret != LDB_SUCCESS) {
 
292
            if (errno) ret = errno;
 
293
            else ret = EIO;
 
294
            goto done;
 
295
        }
 
296
 
 
297
        /* now the requested attribute */
 
298
        for (i = 0; values[i]; i++) {
 
299
            ret = ldb_msg_add_string(msg, attribute, values[i]);
 
300
            if (ret != LDB_SUCCESS) {
 
301
                if (errno) ret = errno;
 
302
                else ret = EIO;
 
303
                goto done;
 
304
            }
 
305
        }
 
306
 
 
307
        ret = ldb_modify(cdb->ldb, msg);
 
308
        if (ret != LDB_SUCCESS) {
 
309
            ret = EIO;
 
310
            goto done;
 
311
        }
 
312
    }
 
313
 
 
314
    ret = EOK;
 
315
 
 
316
done:
 
317
    talloc_free(tmp_ctx);
 
318
    if (ret != EOK) {
 
319
        DEBUG(1, ("Failed to add [%s] to [%s], error [%d] (%s)",
 
320
                  attribute, section, ret, strerror(ret)));
 
321
    }
 
322
    return ret;
 
323
}
 
324
 
 
325
int confdb_get_param(struct confdb_ctx *cdb,
 
326
                     TALLOC_CTX *mem_ctx,
 
327
                     const char *section,
 
328
                     const char *attribute,
 
329
                     char ***values)
 
330
{
 
331
    TALLOC_CTX *tmp_ctx;
 
332
    struct ldb_result *res;
 
333
    struct ldb_dn *dn;
 
334
    char *secdn;
 
335
    const char *attrs[] = { attribute, NULL };
 
336
    char **vals;
 
337
    struct ldb_message_element *el;
 
338
    int ret, i;
 
339
 
 
340
    tmp_ctx = talloc_new(mem_ctx);
 
341
    if (!tmp_ctx)
 
342
        return ENOMEM;
 
343
 
 
344
    ret = parse_section(tmp_ctx, section, &secdn, NULL);
 
345
    if (ret != EOK) {
 
346
        goto done;
 
347
    }
 
348
 
 
349
    dn = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
 
350
    if (!dn) {
 
351
        ret = EIO;
 
352
        goto done;
 
353
    }
 
354
 
 
355
    ret = ldb_search(cdb->ldb, tmp_ctx, &res,
 
356
                     dn, LDB_SCOPE_BASE, attrs, NULL);
 
357
    if (ret != LDB_SUCCESS) {
 
358
        ret = EIO;
 
359
        goto done;
 
360
    }
 
361
    if (res->count > 1) {
 
362
        ret = EIO;
 
363
        goto done;
 
364
    }
 
365
 
 
366
    vals = talloc_zero(mem_ctx, char *);
 
367
    ret = EOK;
 
368
 
 
369
    if (res->count > 0) {
 
370
        el = ldb_msg_find_element(res->msgs[0], attribute);
 
371
        if (el && el->num_values > 0) {
 
372
            vals = talloc_realloc(mem_ctx, vals, char *, el->num_values +1);
 
373
            if (!vals) {
 
374
                ret = ENOMEM;
 
375
                goto done;
 
376
            }
 
377
            /* should always be strings so this should be safe */
 
378
            for (i = 0; i < el->num_values; i++) {
 
379
                struct ldb_val v = el->values[i];
 
380
                vals[i] = talloc_strndup(vals, (char *)v.data, v.length);
 
381
                if (!vals[i]) {
 
382
                    ret = ENOMEM;
 
383
                    goto done;
 
384
                }
 
385
            }
 
386
            vals[i] = NULL;
 
387
        }
 
388
    }
 
389
 
 
390
    *values = vals;
 
391
 
 
392
done:
 
393
    talloc_free(tmp_ctx);
 
394
    if (ret != EOK) {
 
395
        DEBUG(1, ("Failed to get [%s] from [%s], error [%d] (%s)",
 
396
                  attribute, section, ret, strerror(ret)));
 
397
    }
 
398
    return ret;
 
399
}
 
400
 
 
401
int confdb_get_string(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
 
402
                      const char *section, const char *attribute,
 
403
                      const char *defstr, char **result)
 
404
{
 
405
    char **values = NULL;
 
406
    char *restr;
 
407
    int ret;
 
408
 
 
409
    ret = confdb_get_param(cdb, ctx, section, attribute, &values);
 
410
    if (ret != EOK) {
 
411
        goto failed;
 
412
    }
 
413
 
 
414
    if (values[0]) {
 
415
        if (values[1] != NULL) {
 
416
            /* too many values */
 
417
            ret = EINVAL;
 
418
            goto failed;
 
419
        }
 
420
        restr = talloc_steal(ctx, values[0]);
 
421
    } else {
 
422
        /* Did not return a value, so use the default */
 
423
 
 
424
        if (defstr == NULL) { /* No default given */
 
425
            *result = NULL;
 
426
            talloc_free(values);
 
427
            return EOK;
 
428
        }
 
429
 
 
430
        /* Copy the default string */
 
431
        restr = talloc_strdup(ctx, defstr);
 
432
    }
 
433
    if (!restr) {
 
434
        ret = ENOMEM;
 
435
        goto failed;
 
436
    }
 
437
 
 
438
    talloc_free(values);
 
439
 
 
440
    *result = restr;
 
441
    return EOK;
 
442
 
 
443
failed:
 
444
    talloc_free(values);
 
445
    DEBUG(1, ("Failed to get [%s] from [%s], error [%d] (%s)",
 
446
              attribute, section, ret, strerror(ret)));
 
447
    return ret;
 
448
}
 
449
 
 
450
int confdb_get_int(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
 
451
                   const char *section, const char *attribute,
 
452
                   int defval, int *result)
 
453
{
 
454
    char **values = NULL;
 
455
    long val;
 
456
    int ret;
 
457
 
 
458
    ret = confdb_get_param(cdb, ctx, section, attribute, &values);
 
459
    if (ret != EOK) {
 
460
        goto failed;
 
461
    }
 
462
 
 
463
    if (values[0]) {
 
464
        if (values[1] != NULL) {
 
465
            /* too many values */
 
466
            ret = EINVAL;
 
467
            goto failed;
 
468
        }
 
469
 
 
470
        errno = 0;
 
471
        val = strtol(values[0], NULL, 0);
 
472
        if (errno) {
 
473
            ret = errno;
 
474
            goto failed;
 
475
        }
 
476
 
 
477
        if (val < INT_MIN || val > INT_MAX) {
 
478
            ret = ERANGE;
 
479
            goto failed;
 
480
        }
 
481
 
 
482
    } else {
 
483
        val = defval;
 
484
    }
 
485
 
 
486
    talloc_free(values);
 
487
 
 
488
    *result = (int)val;
 
489
    return EOK;
 
490
 
 
491
failed:
 
492
    talloc_free(values);
 
493
    DEBUG(1, ("Failed to read [%s] from [%s], error [%d] (%s)",
 
494
              attribute, section, ret, strerror(ret)));
 
495
    return ret;
 
496
}
 
497
 
 
498
long confdb_get_long(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
 
499
                     const char *section, const char *attribute,
 
500
                     long defval, long *result)
 
501
{
 
502
    char **values = NULL;
 
503
    long val;
 
504
    int ret;
 
505
 
 
506
    ret = confdb_get_param(cdb, ctx, section, attribute, &values);
 
507
    if (ret != EOK) {
 
508
        goto failed;
 
509
    }
 
510
 
 
511
    if (values[0]) {
 
512
        if (values[1] != NULL) {
 
513
            /* too many values */
 
514
            ret = EINVAL;
 
515
            goto failed;
 
516
        }
 
517
 
 
518
        errno = 0;
 
519
        val = strtol(values[0], NULL, 0);
 
520
        if (errno) {
 
521
            ret = errno;
 
522
            goto failed;
 
523
        }
 
524
 
 
525
    } else {
 
526
        val = defval;
 
527
    }
 
528
 
 
529
    talloc_free(values);
 
530
 
 
531
    *result = val;
 
532
    return EOK;
 
533
 
 
534
failed:
 
535
    talloc_free(values);
 
536
    DEBUG(1, ("Failed to read [%s] from [%s], error [%d] (%s)",
 
537
              attribute, section, ret, strerror(ret)));
 
538
    return ret;
 
539
}
 
540
 
 
541
int confdb_get_bool(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
 
542
                    const char *section, const char *attribute,
 
543
                    bool defval, bool *result)
 
544
{
 
545
    char **values = NULL;
 
546
    bool val;
 
547
    int ret;
 
548
 
 
549
    ret = confdb_get_param(cdb, ctx, section, attribute, &values);
 
550
    if (ret != EOK) {
 
551
        goto failed;
 
552
    }
 
553
 
 
554
    if (values[0]) {
 
555
        if (values[1] != NULL) {
 
556
            /* too many values */
 
557
            ret = EINVAL;
 
558
            goto failed;
 
559
        }
 
560
 
 
561
        if (strcasecmp(values[0], "FALSE") == 0) {
 
562
            val = false;
 
563
 
 
564
        } else if (strcasecmp(values[0], "TRUE") == 0) {
 
565
            val = true;
 
566
 
 
567
        } else {
 
568
 
 
569
            DEBUG(2, ("Value is not a boolean!\n"));
 
570
            ret = EINVAL;
 
571
            goto failed;
 
572
        }
 
573
 
 
574
    } else {
 
575
        val = defval;
 
576
    }
 
577
 
 
578
    talloc_free(values);
 
579
 
 
580
    *result = val;
 
581
    return EOK;
 
582
 
 
583
failed:
 
584
    talloc_free(values);
 
585
    DEBUG(1, ("Failed to read [%s] from [%s], error [%d] (%s)",
 
586
              attribute, section, ret, strerror(ret)));
 
587
    return ret;
 
588
}
 
589
 
 
590
/* WARNING: Unlike other similar functions, this one does NOT take a default,
 
591
 * and returns ENOENT if the attribute was not found ! */
 
592
int confdb_get_string_as_list(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
 
593
                              const char *section, const char *attribute,
 
594
                              char ***result)
 
595
{
 
596
    char **values = NULL;
 
597
    int ret;
 
598
 
 
599
    ret = confdb_get_param(cdb, ctx, section, attribute, &values);
 
600
    if (ret != EOK) {
 
601
        goto done;
 
602
    }
 
603
 
 
604
    if (values && values[0]) {
 
605
        if (values[1] != NULL) {
 
606
            /* too many values */
 
607
            ret = EINVAL;
 
608
            goto done;
 
609
        }
 
610
    } else {
 
611
        /* Did not return a value */
 
612
        ret = ENOENT;
 
613
        goto done;
 
614
    }
 
615
 
 
616
    ret = split_on_separator(ctx, values[0], ",", true, result, NULL);
 
617
 
 
618
done:
 
619
    talloc_free(values);
 
620
    if (ret != EOK && ret != ENOENT) {
 
621
        DEBUG(2, ("Failed to get [%s] from [%s], error [%d] (%s)",
 
622
                  attribute, section, ret, strerror(ret)));
 
623
    }
 
624
    return ret;
 
625
}
 
626
 
 
627
int confdb_init(TALLOC_CTX *mem_ctx,
 
628
                struct tevent_context *ev,
 
629
                struct confdb_ctx **cdb_ctx,
 
630
                char *confdb_location)
 
631
{
 
632
    struct confdb_ctx *cdb;
 
633
    int ret = EOK;
 
634
 
 
635
    cdb = talloc_zero(mem_ctx, struct confdb_ctx);
 
636
    if (!cdb)
 
637
        return ENOMEM;
 
638
 
 
639
    /* Because confdb calls use sync ldb calls, we create a separate event
 
640
     * context here. This will prevent the ldb sync calls to start nested
 
641
     * events.
 
642
     * NOTE: this means that we *cannot* do async calls and return in confdb
 
643
     * unless we convert all calls and hook back to the main event context.
 
644
     */
 
645
 
 
646
    cdb->pev = tevent_context_init(cdb);
 
647
    if (!cdb->pev) {
 
648
        talloc_free(cdb);
 
649
        return EIO;
 
650
    }
 
651
 
 
652
    cdb->ldb = ldb_init(cdb, cdb->pev);
 
653
    if (!cdb->ldb) {
 
654
        talloc_free(cdb);
 
655
        return EIO;
 
656
    }
 
657
 
 
658
    ret = ldb_set_debug(cdb->ldb, ldb_debug_messages, NULL);
 
659
    if (ret != LDB_SUCCESS) {
 
660
        DEBUG(0,("Could not set up debug fn.\n"));
 
661
        talloc_free(cdb);
 
662
        return EIO;
 
663
    }
 
664
 
 
665
    ret = ldb_connect(cdb->ldb, confdb_location, 0, NULL);
 
666
    if (ret != LDB_SUCCESS) {
 
667
        talloc_free(cdb);
 
668
        return EIO;
 
669
    }
 
670
 
 
671
    *cdb_ctx = cdb;
 
672
 
 
673
    return EOK;
 
674
}
 
675
 
 
676
int confdb_get_domain(struct confdb_ctx *cdb,
 
677
                      TALLOC_CTX *mem_ctx,
 
678
                      const char *name,
 
679
                      struct sss_domain_info **_domain)
 
680
{
 
681
    struct sss_domain_info *domain;
 
682
    struct ldb_result *res;
 
683
    TALLOC_CTX *tmp_ctx;
 
684
    struct ldb_dn *dn;
 
685
    const char *tmp;
 
686
    int ret;
 
687
 
 
688
    tmp_ctx = talloc_new(mem_ctx);
 
689
    if (!tmp_ctx) return ENOMEM;
 
690
 
 
691
    dn = ldb_dn_new_fmt(tmp_ctx, cdb->ldb,
 
692
                        "cn=%s,%s", name, CONFDB_DOMAIN_BASEDN);
 
693
    if (!dn) {
 
694
        ret = ENOMEM;
 
695
        goto done;
 
696
    }
 
697
 
 
698
    ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn,
 
699
                     LDB_SCOPE_BASE, NULL, NULL);
 
700
    if (ret != LDB_SUCCESS) {
 
701
        ret = EIO;
 
702
        goto done;
 
703
    }
 
704
 
 
705
    if (res->count != 1) {
 
706
        DEBUG(0, ("Unknown domain [%s]\n", name));
 
707
        ret = ENOENT;
 
708
        goto done;
 
709
    }
 
710
 
 
711
    domain = talloc_zero(mem_ctx, struct sss_domain_info);
 
712
    if (!domain) {
 
713
        ret = ENOMEM;
 
714
        goto done;
 
715
    }
 
716
 
 
717
    tmp = ldb_msg_find_attr_as_string(res->msgs[0], "cn", NULL);
 
718
    if (!tmp) {
 
719
        DEBUG(0, ("Invalid configuration entry, fatal error!\n"));
 
720
        ret = EINVAL;
 
721
        goto done;
 
722
    }
 
723
    domain->name = talloc_strdup(domain, tmp);
 
724
    if (!domain->name) {
 
725
        ret = ENOMEM;
 
726
        goto done;
 
727
    }
 
728
 
 
729
    tmp = ldb_msg_find_attr_as_string(res->msgs[0], "provider", NULL);
 
730
    if (tmp) {
 
731
        domain->provider = talloc_strdup(domain, tmp);
 
732
        if (!domain->provider) {
 
733
            ret = ENOMEM;
 
734
            goto done;
 
735
        }
 
736
    }
 
737
    else {
 
738
        DEBUG(0, ("Domain [%s] does not specify a provider, disabling!\n",
 
739
                  domain->name));
 
740
        ret = EINVAL;
 
741
    }
 
742
 
 
743
    domain->timeout = ldb_msg_find_attr_as_int(res->msgs[0],
 
744
                                               "timeout", 0);
 
745
 
 
746
    /* Determine if this domain can be enumerated */
 
747
    domain->enumerate = ldb_msg_find_attr_as_int(res->msgs[0],
 
748
                                                 "enumerate", 0);
 
749
    if (domain->enumerate == 0) {
 
750
        DEBUG(1, ("No enumeration for [%s]!\n", domain->name));
 
751
    }
 
752
 
 
753
    /* Determine if this is a legacy domain */
 
754
    if (ldb_msg_find_attr_as_bool(res->msgs[0], "legacy", 0)) {
 
755
        domain->legacy = true;
 
756
    }
 
757
 
 
758
    /* Determine if this is domain uses MPG */
 
759
    if (strcasecmp(domain->provider, "local") == 0 ||
 
760
        ldb_msg_find_attr_as_bool(res->msgs[0], CONFDB_MPG, 0)) {
 
761
        domain->mpg = true;
 
762
    }
 
763
 
 
764
    /* Determine if user/group names will be Fully Qualified
 
765
     * in NSS interfaces */
 
766
    if (ldb_msg_find_attr_as_bool(res->msgs[0], CONFDB_FQ, 0)) {
 
767
        domain->fqnames = true;
 
768
    }
 
769
 
 
770
    domain->id_min = ldb_msg_find_attr_as_uint(res->msgs[0],
 
771
                                               "minId", SSSD_MIN_ID);
 
772
    domain->id_max = ldb_msg_find_attr_as_uint(res->msgs[0],
 
773
                                               "maxId", 0);
 
774
 
 
775
    /* Do we allow to cache credentials */
 
776
    if (ldb_msg_find_attr_as_bool(res->msgs[0], "cache-credentials", 0)) {
 
777
        domain->cache_credentials = true;
 
778
    }
 
779
 
 
780
    if (ldb_msg_find_attr_as_bool(res->msgs[0], "store-legacy-passwords", 0)) {
 
781
        domain->legacy_passwords = true;
 
782
    }
 
783
 
 
784
    *_domain = domain;
 
785
 
 
786
done:
 
787
    talloc_free(tmp_ctx);
 
788
    return ret;
 
789
}
 
790
 
 
791
int confdb_get_domains(struct confdb_ctx *cdb,
 
792
                       TALLOC_CTX *mem_ctx,
 
793
                       struct sss_domain_info **domains)
 
794
{
 
795
    TALLOC_CTX *tmp_ctx;
 
796
    struct sss_domain_info *domain, *prevdom = NULL;
 
797
    struct sss_domain_info *first = NULL;
 
798
    char **domlist;
 
799
    int ret, i;
 
800
 
 
801
    tmp_ctx = talloc_new(mem_ctx);
 
802
    if (!tmp_ctx) return ENOMEM;
 
803
 
 
804
    ret = confdb_get_string_as_list(cdb, tmp_ctx,
 
805
                                    CONFDB_DOMAINS_PATH, "domains", &domlist);
 
806
    if (ret == ENOENT) {
 
807
        DEBUG(0, ("No domains configured, fatal error!\n"));
 
808
        goto done;
 
809
    }
 
810
    if (ret != EOK ) {
 
811
        DEBUG(0, ("Fatal error retrieving domains list!\n"));
 
812
        goto done;
 
813
    }
 
814
 
 
815
    for (i = 0; domlist[i]; i++) {
 
816
        ret = confdb_get_domain(cdb, mem_ctx, domlist[i], &domain);
 
817
        if (ret) {
 
818
            DEBUG(0, ("Error (%d [%s]) retrieving domain [%s], skipping!\n",
 
819
                      ret, strerror(ret), domlist[i]));
 
820
            ret = EOK;
 
821
            continue;
 
822
        }
 
823
 
 
824
        if (first == NULL) {
 
825
            first = domain;
 
826
            prevdom = first;
 
827
        } else {
 
828
            prevdom->next = domain;
 
829
            prevdom = domain;
 
830
        }
 
831
    }
 
832
 
 
833
    if (first == NULL) {
 
834
        DEBUG(0, ("No domains configured, fatal error!\n"));
 
835
        ret = ENOENT;
 
836
    }
 
837
 
 
838
    *domains = first;
 
839
 
 
840
done:
 
841
    talloc_free(tmp_ctx);
 
842
    return ret;
 
843
}