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

« back to all changes in this revision

Viewing changes to src/db/sysdb.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
   System Database
 
5
 
 
6
   Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
 
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
 
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include "util/util.h"
 
23
#include "util/strtonum.h"
 
24
#include "db/sysdb_private.h"
 
25
#include "confdb/confdb.h"
 
26
#include <time.h>
 
27
 
 
28
#define LDB_MODULES_PATH "LDB_MODULES_PATH"
 
29
 
 
30
static errno_t  sysdb_ldb_connect(TALLOC_CTX *mem_ctx, const char *filename,
 
31
                           struct ldb_context **_ldb)
 
32
{
 
33
    int ret;
 
34
    struct ldb_context *ldb;
 
35
    const char *mod_path;
 
36
 
 
37
    if (_ldb == NULL) {
 
38
        return EINVAL;
 
39
    }
 
40
 
 
41
    ldb = ldb_init(mem_ctx, NULL);
 
42
    if (!ldb) {
 
43
        return EIO;
 
44
    }
 
45
 
 
46
    ret = ldb_set_debug(ldb, ldb_debug_messages, NULL);
 
47
    if (ret != LDB_SUCCESS) {
 
48
        return EIO;
 
49
    }
 
50
 
 
51
    mod_path = getenv(LDB_MODULES_PATH);
 
52
    if (mod_path != NULL) {
 
53
        DEBUG(9, ("Setting ldb module path to [%s].\n", mod_path));
 
54
        ldb_set_modules_dir(ldb, mod_path);
 
55
    }
 
56
 
 
57
    ret = ldb_connect(ldb, filename, 0, NULL);
 
58
    if (ret != LDB_SUCCESS) {
 
59
        return EIO;
 
60
    }
 
61
 
 
62
    *_ldb = ldb;
 
63
 
 
64
    return EOK;
 
65
}
 
66
 
 
67
errno_t sysdb_dn_sanitize(void *mem_ctx, const char *input,
 
68
                          char **sanitized)
 
69
{
 
70
    struct ldb_val val;
 
71
    errno_t ret = EOK;
 
72
 
 
73
    val.data = (uint8_t *)talloc_strdup(mem_ctx, input);
 
74
    if (!val.data) {
 
75
        return ENOMEM;
 
76
    }
 
77
 
 
78
    /* We can't include the trailing NULL because it would
 
79
     * be escaped and result in an unterminated string
 
80
     */
 
81
    val.length = strlen(input);
 
82
 
 
83
    *sanitized = ldb_dn_escape_value(mem_ctx, val);
 
84
    if (!*sanitized) {
 
85
        ret = ENOMEM;
 
86
    }
 
87
 
 
88
    talloc_free(val.data);
 
89
    return ret;
 
90
}
 
91
 
 
92
struct ldb_dn *sysdb_custom_subtree_dn(struct sysdb_ctx *ctx, void *memctx,
 
93
                                       const char *domain,
 
94
                                       const char *subtree_name)
 
95
{
 
96
    errno_t ret;
 
97
    char *clean_subtree;
 
98
    struct ldb_dn *dn = NULL;
 
99
 
 
100
    ret = sysdb_dn_sanitize(NULL, subtree_name, &clean_subtree);
 
101
    if (ret != EOK) {
 
102
        return NULL;
 
103
    }
 
104
 
 
105
    dn = ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
 
106
                        clean_subtree, domain);
 
107
    talloc_free(clean_subtree);
 
108
 
 
109
    return dn;
 
110
}
 
111
struct ldb_dn *sysdb_custom_dn(struct sysdb_ctx *ctx, void *memctx,
 
112
                                const char *domain, const char *object_name,
 
113
                                const char *subtree_name)
 
114
{
 
115
    errno_t ret;
 
116
    TALLOC_CTX *tmp_ctx;
 
117
    char *clean_name;
 
118
    char *clean_subtree;
 
119
    struct ldb_dn *dn = NULL;
 
120
 
 
121
    tmp_ctx = talloc_new(NULL);
 
122
    if (!tmp_ctx) {
 
123
        return NULL;
 
124
    }
 
125
 
 
126
    ret = sysdb_dn_sanitize(tmp_ctx, object_name, &clean_name);
 
127
    if (ret != EOK) {
 
128
        goto done;
 
129
    }
 
130
 
 
131
    ret = sysdb_dn_sanitize(tmp_ctx, subtree_name, &clean_subtree);
 
132
    if (ret != EOK) {
 
133
        goto done;
 
134
    }
 
135
 
 
136
    dn = ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_CUSTOM, clean_name,
 
137
                        clean_subtree, domain);
 
138
 
 
139
done:
 
140
    talloc_free(tmp_ctx);
 
141
    return dn;
 
142
}
 
143
 
 
144
struct ldb_dn *sysdb_user_dn(struct sysdb_ctx *ctx, void *memctx,
 
145
                             const char *domain, const char *name)
 
146
{
 
147
    errno_t ret;
 
148
    char *clean_name;
 
149
    struct ldb_dn *dn;
 
150
 
 
151
    ret = sysdb_dn_sanitize(NULL, name, &clean_name);
 
152
    if (ret != EOK) {
 
153
        return NULL;
 
154
    }
 
155
 
 
156
    dn = ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_USER,
 
157
                        clean_name, domain);
 
158
    talloc_free(clean_name);
 
159
 
 
160
    return dn;
 
161
}
 
162
 
 
163
struct ldb_dn *sysdb_group_dn(struct sysdb_ctx *ctx, void *memctx,
 
164
                              const char *domain, const char *name)
 
165
{
 
166
    errno_t ret;
 
167
    char *clean_name;
 
168
    struct ldb_dn *dn;
 
169
 
 
170
    ret = sysdb_dn_sanitize(NULL, name, &clean_name);
 
171
    if (ret != EOK) {
 
172
        return NULL;
 
173
    }
 
174
 
 
175
    dn = ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_GROUP,
 
176
                        clean_name, domain);
 
177
    talloc_free(clean_name);
 
178
 
 
179
    return dn;
 
180
}
 
181
 
 
182
struct ldb_dn *sysdb_netgroup_dn(struct sysdb_ctx *ctx, void *memctx,
 
183
                                 const char *domain, const char *name)
 
184
{
 
185
    errno_t ret;
 
186
    char *clean_name;
 
187
    struct ldb_dn *dn;
 
188
 
 
189
    ret = sysdb_dn_sanitize(NULL, name, &clean_name);
 
190
    if (ret != EOK) {
 
191
        return NULL;
 
192
    }
 
193
 
 
194
    dn = ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_NETGROUP,
 
195
                        clean_name, domain);
 
196
    talloc_free(clean_name);
 
197
 
 
198
    return dn;
 
199
}
 
200
 
 
201
struct ldb_dn *sysdb_netgroup_base_dn(struct sysdb_ctx *ctx, void *memctx,
 
202
                                 const char *domain)
 
203
{
 
204
    return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_TMPL_NETGROUP_BASE, domain);
 
205
}
 
206
 
 
207
errno_t sysdb_get_rdn(struct sysdb_ctx *ctx, void *memctx,
 
208
                      const char *_dn, char **_name, char **_val)
 
209
{
 
210
    errno_t ret;
 
211
    struct ldb_dn *dn;
 
212
    const char *attr_name = NULL;
 
213
    const struct ldb_val *val;
 
214
    TALLOC_CTX *tmpctx;
 
215
 
 
216
    /* We have to create a tmpctx here because
 
217
     * ldb_dn_new_fmt() fails if memctx is NULL
 
218
     */
 
219
    tmpctx = talloc_new(NULL);
 
220
    if (!tmpctx) {
 
221
        return ENOMEM;
 
222
    }
 
223
 
 
224
    dn = ldb_dn_new_fmt(tmpctx, ctx->ldb, "%s", _dn);
 
225
    if (dn == NULL) {
 
226
        ret = ENOMEM;
 
227
        goto done;
 
228
    }
 
229
 
 
230
    if (_name) {
 
231
        attr_name = ldb_dn_get_rdn_name(dn);
 
232
        if (attr_name == NULL) {
 
233
            ret = EINVAL;
 
234
            goto done;
 
235
        }
 
236
 
 
237
        *_name = talloc_strdup(memctx, attr_name);
 
238
        if (!*_name) {
 
239
            ret = ENOMEM;
 
240
            goto done;
 
241
        }
 
242
    }
 
243
 
 
244
    val = ldb_dn_get_rdn_val(dn);
 
245
    if (val == NULL) {
 
246
        ret = EINVAL;
 
247
        if (_name) talloc_free(*_name);
 
248
        goto done;
 
249
    }
 
250
 
 
251
    *_val = talloc_strndup(memctx, (char *) val->data, val->length);
 
252
    if (!*_val) {
 
253
        ret = ENOMEM;
 
254
        if (_name) talloc_free(*_name);
 
255
        goto done;
 
256
    }
 
257
 
 
258
    ret = EOK;
 
259
 
 
260
done:
 
261
    talloc_zfree(tmpctx);
 
262
    return ret;
 
263
}
 
264
 
 
265
errno_t sysdb_group_dn_name(struct sysdb_ctx *ctx, void *memctx,
 
266
                            const char *_dn, char **_name)
 
267
{
 
268
    return sysdb_get_rdn(ctx, memctx, _dn, NULL, _name);
 
269
}
 
270
 
 
271
struct ldb_dn *sysdb_domain_dn(struct sysdb_ctx *ctx, void *memctx,
 
272
                              const char *domain)
 
273
{
 
274
    return ldb_dn_new_fmt(memctx, ctx->ldb, SYSDB_DOM_BASE, domain);
 
275
}
 
276
 
 
277
struct ldb_context *sysdb_ctx_get_ldb(struct sysdb_ctx *ctx)
 
278
{
 
279
    return ctx->ldb;
 
280
}
 
281
 
 
282
struct sysdb_attrs *sysdb_new_attrs(TALLOC_CTX *memctx)
 
283
{
 
284
    return talloc_zero(memctx, struct sysdb_attrs);
 
285
}
 
286
 
 
287
static int sysdb_attrs_get_el_int(struct sysdb_attrs *attrs, const char *name,
 
288
                                  bool alloc, struct ldb_message_element **el)
 
289
{
 
290
    struct ldb_message_element *e = NULL;
 
291
    int i;
 
292
 
 
293
    for (i = 0; i < attrs->num; i++) {
 
294
        if (strcasecmp(name, attrs->a[i].name) == 0)
 
295
            e = &(attrs->a[i]);
 
296
    }
 
297
 
 
298
    if (!e && alloc) {
 
299
        e = talloc_realloc(attrs, attrs->a,
 
300
                           struct ldb_message_element, attrs->num+1);
 
301
        if (!e) return ENOMEM;
 
302
        attrs->a = e;
 
303
 
 
304
        e[attrs->num].name = talloc_strdup(e, name);
 
305
        if (!e[attrs->num].name) return ENOMEM;
 
306
 
 
307
        e[attrs->num].num_values = 0;
 
308
        e[attrs->num].values = NULL;
 
309
        e[attrs->num].flags = 0;
 
310
 
 
311
        e = &(attrs->a[attrs->num]);
 
312
        attrs->num++;
 
313
    }
 
314
 
 
315
    if (!e) {
 
316
        return ENOENT;
 
317
    }
 
318
 
 
319
    *el = e;
 
320
 
 
321
    return EOK;
 
322
}
 
323
 
 
324
int sysdb_attrs_get_el(struct sysdb_attrs *attrs, const char *name,
 
325
                       struct ldb_message_element **el)
 
326
{
 
327
    return sysdb_attrs_get_el_int(attrs, name, true, el);
 
328
}
 
329
 
 
330
int sysdb_attrs_get_string(struct sysdb_attrs *attrs, const char *name,
 
331
                           const char **string)
 
332
{
 
333
    struct ldb_message_element *el;
 
334
    int ret;
 
335
 
 
336
    ret = sysdb_attrs_get_el_int(attrs, name, false, &el);
 
337
    if (ret) {
 
338
        return ret;
 
339
    }
 
340
 
 
341
    if (el->num_values != 1) {
 
342
        return ERANGE;
 
343
    }
 
344
 
 
345
    *string = (const char *)el->values[0].data;
 
346
    return EOK;
 
347
}
 
348
 
 
349
int sysdb_attrs_get_uint32_t(struct sysdb_attrs *attrs, const char *name,
 
350
                             uint32_t *value)
 
351
{
 
352
    struct ldb_message_element *el;
 
353
    int ret;
 
354
    char *endptr;
 
355
    uint32_t val;
 
356
 
 
357
    ret = sysdb_attrs_get_el_int(attrs, name, false, &el);
 
358
    if (ret) {
 
359
        return ret;
 
360
    }
 
361
 
 
362
    if (el->num_values != 1) {
 
363
        return ERANGE;
 
364
    }
 
365
 
 
366
    errno = 0;
 
367
    val = strtouint32((const char *) el->values[0].data, &endptr, 0);
 
368
    if (errno != 0) return errno;
 
369
    if (*endptr) return EINVAL;
 
370
 
 
371
    *value = val;
 
372
    return EOK;
 
373
}
 
374
 
 
375
int sysdb_attrs_get_string_array(struct sysdb_attrs *attrs, const char *name,
 
376
                                 TALLOC_CTX *mem_ctx, const char ***string)
 
377
{
 
378
    struct ldb_message_element *el;
 
379
    int ret;
 
380
    unsigned int u;
 
381
    const char **a;
 
382
 
 
383
    ret = sysdb_attrs_get_el_int(attrs, name, false, &el);
 
384
    if (ret) {
 
385
        return ret;
 
386
    }
 
387
 
 
388
    a = talloc_array(mem_ctx, const char *, el->num_values + 1);
 
389
    if (a == NULL) {
 
390
        return ENOMEM;
 
391
    }
 
392
 
 
393
    memset(a, 0, sizeof(const char *) * (el->num_values + 1));
 
394
 
 
395
    for(u = 0; u < el->num_values; u++) {
 
396
        a[u] = talloc_strndup(a, (const char *)el->values[u].data,
 
397
                              el->values[u].length);
 
398
        if (a[u] == NULL) {
 
399
            talloc_free(a);
 
400
            return ENOMEM;
 
401
        }
 
402
    }
 
403
 
 
404
    *string = a;
 
405
    return EOK;
 
406
}
 
407
 
 
408
int sysdb_attrs_add_val(struct sysdb_attrs *attrs,
 
409
                        const char *name, const struct ldb_val *val)
 
410
{
 
411
    struct ldb_message_element *el = NULL;
 
412
    struct ldb_val *vals;
 
413
    int ret;
 
414
 
 
415
    ret = sysdb_attrs_get_el(attrs, name, &el);
 
416
    if (ret != EOK) {
 
417
        return ret;
 
418
    }
 
419
 
 
420
    vals = talloc_realloc(attrs->a, el->values,
 
421
                          struct ldb_val, el->num_values+1);
 
422
    if (!vals) return ENOMEM;
 
423
 
 
424
    vals[el->num_values] = ldb_val_dup(vals, val);
 
425
    if (vals[el->num_values].data == NULL &&
 
426
        vals[el->num_values].length != 0) {
 
427
        return ENOMEM;
 
428
    }
 
429
 
 
430
    el->values = vals;
 
431
    el->num_values++;
 
432
 
 
433
    return EOK;
 
434
}
 
435
 
 
436
int sysdb_attrs_add_string(struct sysdb_attrs *attrs,
 
437
                           const char *name, const char *str)
 
438
{
 
439
    struct ldb_val v;
 
440
 
 
441
    v.data = (uint8_t *)discard_const(str);
 
442
    v.length = strlen(str);
 
443
 
 
444
    return sysdb_attrs_add_val(attrs, name, &v);
 
445
}
 
446
 
 
447
int sysdb_attrs_add_bool(struct sysdb_attrs *attrs,
 
448
                         const char *name, bool value)
 
449
{
 
450
    if(value) {
 
451
        return sysdb_attrs_add_string(attrs, name, "TRUE");
 
452
    }
 
453
 
 
454
    return sysdb_attrs_add_string(attrs, name, "FALSE");
 
455
}
 
456
 
 
457
int sysdb_attrs_steal_string(struct sysdb_attrs *attrs,
 
458
                             const char *name, char *str)
 
459
{
 
460
    struct ldb_message_element *el = NULL;
 
461
    struct ldb_val *vals;
 
462
    int ret;
 
463
 
 
464
    ret = sysdb_attrs_get_el(attrs, name, &el);
 
465
 
 
466
    vals = talloc_realloc(attrs->a, el->values,
 
467
                          struct ldb_val, el->num_values+1);
 
468
    if (!vals) return ENOMEM;
 
469
    el->values = vals;
 
470
 
 
471
    /* now steal and assign the string */
 
472
    talloc_steal(el->values, str);
 
473
 
 
474
    el->values[el->num_values].data = (uint8_t *)str;
 
475
    el->values[el->num_values].length = strlen(str);
 
476
    el->num_values++;
 
477
 
 
478
    return EOK;
 
479
}
 
480
 
 
481
int sysdb_attrs_add_long(struct sysdb_attrs *attrs,
 
482
                         const char *name, long value)
 
483
{
 
484
    struct ldb_val v;
 
485
    char *str;
 
486
    int ret;
 
487
 
 
488
    str = talloc_asprintf(attrs, "%ld", value);
 
489
    if (!str) return ENOMEM;
 
490
 
 
491
    v.data = (uint8_t *)str;
 
492
    v.length = strlen(str);
 
493
 
 
494
    ret = sysdb_attrs_add_val(attrs, name, &v);
 
495
    talloc_free(str);
 
496
 
 
497
    return ret;
 
498
}
 
499
 
 
500
int sysdb_attrs_add_uint32(struct sysdb_attrs *attrs,
 
501
                           const char *name, uint32_t value)
 
502
{
 
503
    unsigned long val = value;
 
504
    struct ldb_val v;
 
505
    char *str;
 
506
    int ret;
 
507
 
 
508
    str = talloc_asprintf(attrs, "%lu", val);
 
509
    if (!str) return ENOMEM;
 
510
 
 
511
    v.data = (uint8_t *)str;
 
512
    v.length = strlen(str);
 
513
 
 
514
    ret = sysdb_attrs_add_val(attrs, name, &v);
 
515
    talloc_free(str);
 
516
 
 
517
    return ret;
 
518
}
 
519
 
 
520
int sysdb_attrs_add_time_t(struct sysdb_attrs *attrs,
 
521
                           const char *name, time_t value)
 
522
{
 
523
    long long val = value;
 
524
    struct ldb_val v;
 
525
    char *str;
 
526
    int ret;
 
527
 
 
528
    str = talloc_asprintf(attrs, "%lld", val);
 
529
    if (!str) return ENOMEM;
 
530
 
 
531
    v.data = (uint8_t *)str;
 
532
    v.length = strlen(str);
 
533
 
 
534
    ret = sysdb_attrs_add_val(attrs, name, &v);
 
535
    talloc_free(str);
 
536
 
 
537
    return ret;
 
538
}
 
539
 
 
540
int sysdb_attrs_users_from_str_list(struct sysdb_attrs *attrs,
 
541
                                    const char *attr_name,
 
542
                                    const char *domain,
 
543
                                    const char *const *list)
 
544
{
 
545
    struct ldb_message_element *el = NULL;
 
546
    struct ldb_val *vals;
 
547
    int i, j, num;
 
548
    char *member;
 
549
    int ret;
 
550
 
 
551
    ret = sysdb_attrs_get_el(attrs, attr_name, &el);
 
552
    if (ret) {
 
553
        return ret;
 
554
    }
 
555
 
 
556
    for (num = 0; list[num]; num++) /* count */ ;
 
557
 
 
558
    vals = talloc_realloc(attrs->a, el->values,
 
559
                          struct ldb_val, el->num_values + num);
 
560
    if (!vals) {
 
561
        return ENOMEM;
 
562
    }
 
563
    el->values = vals;
 
564
 
 
565
    DEBUG(9, ("Adding %d members to existing %d ones\n",
 
566
              num, el->num_values));
 
567
 
 
568
    for (i = 0, j = el->num_values; i < num; i++) {
 
569
 
 
570
        member = sysdb_user_strdn(el->values, domain, list[i]);
 
571
        if (!member) {
 
572
            DEBUG(4, ("Failed to get user dn for [%s]\n", list[i]));
 
573
            continue;
 
574
        }
 
575
        el->values[j].data = (uint8_t *)member;
 
576
        el->values[j].length = strlen(member);
 
577
        j++;
 
578
 
 
579
        DEBUG(7, ("    member #%d: [%s]\n", i, member));
 
580
    }
 
581
    el->num_values = j;
 
582
 
 
583
    return EOK;
 
584
}
 
585
 
 
586
int sysdb_attrs_users_from_ldb_vals(struct sysdb_attrs *attrs,
 
587
                                    const char *attr_name,
 
588
                                    const char *domain,
 
589
                                    struct ldb_val *values,
 
590
                                    int num_values)
 
591
{
 
592
    struct ldb_message_element *el = NULL;
 
593
    struct ldb_val *vals;
 
594
    int i, j;
 
595
    char *member;
 
596
    int ret;
 
597
 
 
598
    ret = sysdb_attrs_get_el(attrs, attr_name, &el);
 
599
    if (ret) {
 
600
        return ret;
 
601
    }
 
602
 
 
603
    vals = talloc_realloc(attrs->a, el->values, struct ldb_val,
 
604
                          el->num_values + num_values);
 
605
    if (!vals) {
 
606
        return ENOMEM;
 
607
    }
 
608
    el->values = vals;
 
609
 
 
610
    DEBUG(9, ("Adding %d members to existing %d ones\n",
 
611
              num_values, el->num_values));
 
612
 
 
613
    for (i = 0, j = el->num_values; i < num_values; i++) {
 
614
        member = sysdb_user_strdn(el->values, domain,
 
615
                                  (char *)values[i].data);
 
616
        if (!member) {
 
617
            DEBUG(4, ("Failed to get user dn for [%s]\n",
 
618
                      (char *)values[i].data));
 
619
            return ENOMEM;
 
620
        }
 
621
        el->values[j].data = (uint8_t *)member;
 
622
        el->values[j].length = strlen(member);
 
623
        j++;
 
624
 
 
625
        DEBUG(7, ("    member #%d: [%s]\n", i, member));
 
626
    }
 
627
    el->num_values = j;
 
628
 
 
629
    return EOK;
 
630
}
 
631
 
 
632
static char *build_dom_dn_str_escape(TALLOC_CTX *memctx, const char *template,
 
633
                                     const char *domain, const char *name)
 
634
{
 
635
    char *ret;
 
636
    int l;
 
637
 
 
638
    l = strcspn(name, ",=\n+<>#;\\\"");
 
639
    if (name[l] != '\0') {
 
640
        struct ldb_val v;
 
641
        char *tmp;
 
642
 
 
643
        v.data = discard_const_p(uint8_t, name);
 
644
        v.length = strlen(name);
 
645
 
 
646
        tmp = ldb_dn_escape_value(memctx, v);
 
647
        if (!tmp) {
 
648
            return NULL;
 
649
        }
 
650
 
 
651
        ret = talloc_asprintf(memctx, template, tmp, domain);
 
652
        talloc_zfree(tmp);
 
653
        if (!ret) {
 
654
            return NULL;
 
655
        }
 
656
 
 
657
        return ret;
 
658
    }
 
659
 
 
660
    ret = talloc_asprintf(memctx, template, name, domain);
 
661
    if (!ret) {
 
662
        return NULL;
 
663
    }
 
664
 
 
665
    return ret;
 
666
}
 
667
 
 
668
char *sysdb_user_strdn(TALLOC_CTX *memctx,
 
669
                       const char *domain, const char *name)
 
670
{
 
671
    return build_dom_dn_str_escape(memctx, SYSDB_TMPL_USER, domain, name);
 
672
}
 
673
 
 
674
char *sysdb_group_strdn(TALLOC_CTX *memctx,
 
675
                        const char *domain, const char *name)
 
676
{
 
677
    return build_dom_dn_str_escape(memctx, SYSDB_TMPL_GROUP, domain, name);
 
678
}
 
679
 
 
680
/* TODO: make a more complete and precise mapping */
 
681
int sysdb_error_to_errno(int ldberr)
 
682
{
 
683
    switch (ldberr) {
 
684
    case LDB_SUCCESS:
 
685
        return EOK;
 
686
    case LDB_ERR_OPERATIONS_ERROR:
 
687
        return EIO;
 
688
    case LDB_ERR_NO_SUCH_OBJECT:
 
689
        return ENOENT;
 
690
    case LDB_ERR_BUSY:
 
691
        return EBUSY;
 
692
    case LDB_ERR_ENTRY_ALREADY_EXISTS:
 
693
        return EEXIST;
 
694
    default:
 
695
        return EFAULT;
 
696
    }
 
697
}
 
698
 
 
699
/* =Transactions========================================================== */
 
700
 
 
701
int sysdb_transaction_start(struct sysdb_ctx *ctx)
 
702
{
 
703
    int ret;
 
704
 
 
705
    ret = ldb_transaction_start(ctx->ldb);
 
706
    if (ret != LDB_SUCCESS) {
 
707
        DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
 
708
    }
 
709
    return sysdb_error_to_errno(ret);
 
710
}
 
711
 
 
712
int sysdb_transaction_commit(struct sysdb_ctx *ctx)
 
713
{
 
714
    int ret;
 
715
 
 
716
    ret = ldb_transaction_commit(ctx->ldb);
 
717
    if (ret != LDB_SUCCESS) {
 
718
        DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
 
719
    }
 
720
    return sysdb_error_to_errno(ret);
 
721
}
 
722
 
 
723
int sysdb_transaction_cancel(struct sysdb_ctx *ctx)
 
724
{
 
725
    int ret;
 
726
 
 
727
    ret = ldb_transaction_cancel(ctx->ldb);
 
728
    if (ret != LDB_SUCCESS) {
 
729
        DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
 
730
    }
 
731
    return sysdb_error_to_errno(ret);
 
732
}
 
733
 
 
734
/* =Initialization======================================================== */
 
735
 
 
736
static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
 
737
                                      struct sss_domain_info *domain,
 
738
                                      const char *db_path,
 
739
                                      bool allow_upgrade,
 
740
                                      struct sysdb_ctx **_ctx);
 
741
 
 
742
static int sysdb_get_db_file(TALLOC_CTX *mem_ctx,
 
743
                             const char *provider, const char *name,
 
744
                             const char *base_path, char **_ldb_file)
 
745
{
 
746
    char *ldb_file;
 
747
 
 
748
    /* special case for the local domain */
 
749
    if (strcasecmp(provider, "local") == 0) {
 
750
        ldb_file = talloc_asprintf(mem_ctx, "%s/"LOCAL_SYSDB_FILE,
 
751
                                   base_path);
 
752
    } else {
 
753
        ldb_file = talloc_asprintf(mem_ctx, "%s/"CACHE_SYSDB_FILE,
 
754
                                   base_path, name);
 
755
    }
 
756
    if (!ldb_file) {
 
757
        return ENOMEM;
 
758
    }
 
759
 
 
760
    *_ldb_file = ldb_file;
 
761
    return EOK;
 
762
}
 
763
 
 
764
/* serach all groups that have a memberUid attribute.
 
765
 * change it into a member attribute for a user of same domain.
 
766
 * remove the memberUid attribute
 
767
 * add the new member attribute
 
768
 * finally stop indexing memberUid
 
769
 * upgrade version to 0.2
 
770
 */
 
771
static int sysdb_upgrade_01(TALLOC_CTX *mem_ctx,
 
772
                            struct ldb_context *ldb,
 
773
                            const char **ver)
 
774
{
 
775
    struct ldb_message_element *el;
 
776
    struct ldb_result *res;
 
777
    struct ldb_dn *basedn;
 
778
    struct ldb_dn *mem_dn;
 
779
    struct ldb_message *msg;
 
780
    const struct ldb_val *val;
 
781
    const char *filter = "(&(memberUid=*)(objectclass=group))";
 
782
    const char *attrs[] = { "memberUid", NULL };
 
783
    const char *mdn;
 
784
    char *domain;
 
785
    int ret, i, j;
 
786
 
 
787
    basedn = ldb_dn_new(mem_ctx, ldb, "cn=sysdb");
 
788
    if (!basedn) {
 
789
        ret = EIO;
 
790
        goto done;
 
791
    }
 
792
 
 
793
    ret = ldb_search(ldb, mem_ctx, &res,
 
794
                     basedn, LDB_SCOPE_SUBTREE,
 
795
                     attrs, filter);
 
796
    if (ret != LDB_SUCCESS) {
 
797
        ret = EIO;
 
798
        goto done;
 
799
    }
 
800
 
 
801
    ret = ldb_transaction_start(ldb);
 
802
    if (ret != LDB_SUCCESS) {
 
803
        ret = EIO;
 
804
        goto done;
 
805
    }
 
806
 
 
807
    for (i = 0; i < res->count; i++) {
 
808
        el = ldb_msg_find_element(res->msgs[i], "memberUid");
 
809
        if (!el) {
 
810
            DEBUG(1, ("memberUid is missing from message [%s], skipping\n",
 
811
                      ldb_dn_get_linearized(res->msgs[i]->dn)));
 
812
            continue;
 
813
        }
 
814
 
 
815
        /* create modification message */
 
816
        msg = ldb_msg_new(mem_ctx);
 
817
        if (!msg) {
 
818
            ret = ENOMEM;
 
819
            goto done;
 
820
        }
 
821
        msg->dn = res->msgs[i]->dn;
 
822
 
 
823
        ret = ldb_msg_add_empty(msg, "memberUid", LDB_FLAG_MOD_DELETE, NULL);
 
824
        if (ret != LDB_SUCCESS) {
 
825
            ret = ENOMEM;
 
826
            goto done;
 
827
        }
 
828
 
 
829
        ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, LDB_FLAG_MOD_ADD, NULL);
 
830
        if (ret != LDB_SUCCESS) {
 
831
            ret = ENOMEM;
 
832
            goto done;
 
833
        }
 
834
 
 
835
        /* get domain name component value */
 
836
        val = ldb_dn_get_component_val(res->msgs[i]->dn, 2);
 
837
        domain = talloc_strndup(mem_ctx, (const char *)val->data, val->length);
 
838
        if (!domain) {
 
839
            ret = ENOMEM;
 
840
            goto done;
 
841
        }
 
842
 
 
843
        for (j = 0; j < el->num_values; j++) {
 
844
            mem_dn = ldb_dn_new_fmt(mem_ctx, ldb, SYSDB_TMPL_USER,
 
845
                                    (const char *)el->values[j].data, domain);
 
846
            if (!mem_dn) {
 
847
                ret = ENOMEM;
 
848
                goto done;
 
849
            }
 
850
 
 
851
            mdn = talloc_strdup(msg, ldb_dn_get_linearized(mem_dn));
 
852
            if (!mdn) {
 
853
                ret = ENOMEM;
 
854
                goto done;
 
855
            }
 
856
            ret = ldb_msg_add_string(msg, SYSDB_MEMBER, mdn);
 
857
            if (ret != LDB_SUCCESS) {
 
858
                ret = ENOMEM;
 
859
                goto done;
 
860
            }
 
861
 
 
862
            talloc_zfree(mem_dn);
 
863
        }
 
864
 
 
865
        /* ok now we are ready to modify the entry */
 
866
        ret = ldb_modify(ldb, msg);
 
867
        if (ret != LDB_SUCCESS) {
 
868
            ret = sysdb_error_to_errno(ret);
 
869
            goto done;
 
870
        }
 
871
 
 
872
        talloc_zfree(msg);
 
873
    }
 
874
 
 
875
    /* conversion done, upgrade version number */
 
876
    msg = ldb_msg_new(mem_ctx);
 
877
    if (!msg) {
 
878
        ret = ENOMEM;
 
879
        goto done;
 
880
    }
 
881
    msg->dn = ldb_dn_new(mem_ctx, ldb, "cn=sysdb");
 
882
    if (!msg->dn) {
 
883
        ret = ENOMEM;
 
884
        goto done;
 
885
    }
 
886
 
 
887
    ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL);
 
888
    if (ret != LDB_SUCCESS) {
 
889
        ret = ENOMEM;
 
890
        goto done;
 
891
    }
 
892
    ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_2);
 
893
    if (ret != LDB_SUCCESS) {
 
894
        ret = ENOMEM;
 
895
        goto done;
 
896
    }
 
897
 
 
898
    ret = ldb_modify(ldb, msg);
 
899
    if (ret != LDB_SUCCESS) {
 
900
        ret = sysdb_error_to_errno(ret);
 
901
        goto done;
 
902
    }
 
903
 
 
904
    ret = EOK;
 
905
 
 
906
done:
 
907
    if (ret != EOK) {
 
908
        ldb_transaction_cancel(ldb);
 
909
    } else {
 
910
        ret = ldb_transaction_commit(ldb);
 
911
        if (ret != LDB_SUCCESS) {
 
912
            return EIO;
 
913
        }
 
914
 
 
915
        *ver = SYSDB_VERSION_0_2;
 
916
    }
 
917
 
 
918
    return ret;
 
919
}
 
920
 
 
921
static int sysdb_check_upgrade_02(TALLOC_CTX *mem_ctx,
 
922
                                  struct sss_domain_info *domains,
 
923
                                  const char *db_path)
 
924
{
 
925
    TALLOC_CTX *tmp_ctx = NULL;
 
926
    struct ldb_context *ldb;
 
927
    char *ldb_file;
 
928
    struct sysdb_ctx *ctx;
 
929
    struct sss_domain_info *dom;
 
930
    struct ldb_message_element *el;
 
931
    struct ldb_message *msg;
 
932
    struct ldb_result *res;
 
933
    struct ldb_dn *verdn;
 
934
    const char *version = NULL;
 
935
    bool do_02_upgrade = false;
 
936
    bool ctx_trans = false;
 
937
    int ret;
 
938
 
 
939
    tmp_ctx = talloc_new(mem_ctx);
 
940
    if (!tmp_ctx) {
 
941
        return ENOMEM;
 
942
    }
 
943
 
 
944
    ret = sysdb_get_db_file(mem_ctx,
 
945
                            "local", "UPGRADE",
 
946
                            db_path, &ldb_file);
 
947
    if (ret != EOK) {
 
948
        goto exit;
 
949
    }
 
950
 
 
951
    ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb);
 
952
    if (ret != EOK) {
 
953
        DEBUG(1, ("sysdb_ldb_connect failed.\n"));
 
954
        return ret;
 
955
    }
 
956
 
 
957
    verdn = ldb_dn_new(tmp_ctx, ldb, "cn=sysdb");
 
958
    if (!verdn) {
 
959
        ret = EIO;
 
960
        goto exit;
 
961
    }
 
962
 
 
963
    ret = ldb_search(ldb, tmp_ctx, &res,
 
964
                     verdn, LDB_SCOPE_BASE,
 
965
                     NULL, NULL);
 
966
    if (ret != LDB_SUCCESS) {
 
967
        ret = EIO;
 
968
        goto exit;
 
969
    }
 
970
    if (res->count > 1) {
 
971
        ret = EIO;
 
972
        goto exit;
 
973
    }
 
974
 
 
975
    if (res->count == 1) {
 
976
        el = ldb_msg_find_element(res->msgs[0], "version");
 
977
        if (el) {
 
978
            if (el->num_values != 1) {
 
979
                ret = EINVAL;
 
980
                goto exit;
 
981
            }
 
982
            version = talloc_strndup(tmp_ctx,
 
983
                                     (char *)(el->values[0].data),
 
984
                                     el->values[0].length);
 
985
            if (!version) {
 
986
                ret = ENOMEM;
 
987
                goto exit;
 
988
            }
 
989
 
 
990
            if (strcmp(version, SYSDB_VERSION) == 0) {
 
991
                /* all fine, return */
 
992
                ret = EOK;
 
993
                goto exit;
 
994
            }
 
995
 
 
996
            DEBUG(4, ("Upgrading DB from version: %s\n", version));
 
997
 
 
998
            if (strcmp(version, SYSDB_VERSION_0_1) == 0) {
 
999
                /* convert database */
 
1000
                ret = sysdb_upgrade_01(tmp_ctx, ldb, &version);
 
1001
                if (ret != EOK) goto exit;
 
1002
            }
 
1003
 
 
1004
            if (strcmp(version, SYSDB_VERSION_0_2) == 0) {
 
1005
                /* need to convert database to split files */
 
1006
                do_02_upgrade = true;
 
1007
            }
 
1008
 
 
1009
        }
 
1010
    }
 
1011
 
 
1012
    if (!do_02_upgrade) {
 
1013
        /* not a v2 upgrade, return and let the normal code take over any
 
1014
        * further upgrade */
 
1015
        ret = EOK;
 
1016
        goto exit;
 
1017
    }
 
1018
 
 
1019
    /* == V2->V3 UPGRADE == */
 
1020
 
 
1021
    DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_3));
 
1022
 
 
1023
    /* ldb uses posix locks,
 
1024
     * posix is stupid and kills all locks when you close *any* file
 
1025
     * descriptor associated to the same file.
 
1026
     * Therefore we must close and reopen the ldb file here */
 
1027
 
 
1028
    /* == Backup and reopen ldb == */
 
1029
 
 
1030
    /* close */
 
1031
    talloc_zfree(ldb);
 
1032
 
 
1033
    /* backup*/
 
1034
    ret = backup_file(ldb_file, 0);
 
1035
    if (ret != EOK) {
 
1036
        goto exit;
 
1037
    }
 
1038
 
 
1039
    /* reopen */
 
1040
    ret = sysdb_ldb_connect(tmp_ctx, ldb_file, &ldb);
 
1041
    if (ret != EOK) {
 
1042
        DEBUG(1, ("sysdb_ldb_connect failed.\n"));
 
1043
        return ret;
 
1044
    }
 
1045
 
 
1046
    /* open a transaction */
 
1047
    ret = ldb_transaction_start(ldb);
 
1048
    if (ret != LDB_SUCCESS) {
 
1049
        DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
 
1050
        ret = EIO;
 
1051
        goto exit;
 
1052
    }
 
1053
 
 
1054
    /* == Upgrade contents == */
 
1055
 
 
1056
    for (dom = domains; dom; dom = dom->next) {
 
1057
        struct ldb_dn *domain_dn;
 
1058
        struct ldb_dn *users_dn;
 
1059
        struct ldb_dn *groups_dn;
 
1060
        int i;
 
1061
 
 
1062
        /* skip local */
 
1063
        if (strcasecmp(dom->provider, "local") == 0) {
 
1064
            continue;
 
1065
        }
 
1066
 
 
1067
        /* create new dom db */
 
1068
        ret = sysdb_domain_init_internal(tmp_ctx, dom,
 
1069
                                         db_path, false, &ctx);
 
1070
        if (ret != EOK) {
 
1071
            goto done;
 
1072
        }
 
1073
 
 
1074
        ret = ldb_transaction_start(ctx->ldb);
 
1075
        if (ret != LDB_SUCCESS) {
 
1076
            DEBUG(1, ("Failed to start ldb transaction! (%d)\n", ret));
 
1077
            ret = EIO;
 
1078
            goto done;
 
1079
        }
 
1080
        ctx_trans = true;
 
1081
 
 
1082
        /* search all entries for this domain in local,
 
1083
         * copy them all in the new database,
 
1084
         * then remove them from local */
 
1085
 
 
1086
        domain_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
 
1087
                                   SYSDB_DOM_BASE, ctx->domain->name);
 
1088
        if (!domain_dn) {
 
1089
            ret = ENOMEM;
 
1090
            goto done;
 
1091
        }
 
1092
 
 
1093
        ret = ldb_search(ldb, tmp_ctx, &res,
 
1094
                         domain_dn, LDB_SCOPE_SUBTREE,
 
1095
                         NULL, NULL);
 
1096
        if (ret != LDB_SUCCESS) {
 
1097
            ret = EIO;
 
1098
            goto done;
 
1099
        }
 
1100
 
 
1101
        users_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
 
1102
                                 SYSDB_TMPL_USER_BASE, ctx->domain->name);
 
1103
        if (!users_dn) {
 
1104
            ret = ENOMEM;
 
1105
            goto done;
 
1106
        }
 
1107
        groups_dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
 
1108
                                   SYSDB_TMPL_GROUP_BASE, ctx->domain->name);
 
1109
        if (!groups_dn) {
 
1110
            ret = ENOMEM;
 
1111
            goto done;
 
1112
        }
 
1113
 
 
1114
        for (i = 0; i < res->count; i++) {
 
1115
 
 
1116
            struct ldb_dn *orig_dn;
 
1117
 
 
1118
            msg = res->msgs[i];
 
1119
 
 
1120
            /* skip pre-created congtainers */
 
1121
            if ((ldb_dn_compare(msg->dn, domain_dn) == 0) ||
 
1122
                (ldb_dn_compare(msg->dn, users_dn) == 0) ||
 
1123
                (ldb_dn_compare(msg->dn, groups_dn) == 0)) {
 
1124
                continue;
 
1125
            }
 
1126
 
 
1127
            /* regenerate the DN against the new ldb as it may have different
 
1128
             * casefolding rules (example: name changing from case insensitive
 
1129
             * to case sensitive) */
 
1130
            orig_dn = msg->dn;
 
1131
            msg->dn = ldb_dn_new(msg, ctx->ldb,
 
1132
                                 ldb_dn_get_linearized(orig_dn));
 
1133
            if (!msg->dn) {
 
1134
                ret = ENOMEM;
 
1135
                goto done;
 
1136
            }
 
1137
 
 
1138
            ret = ldb_add(ctx->ldb, msg);
 
1139
            if (ret != LDB_SUCCESS) {
 
1140
                DEBUG(0, ("WARNING: Could not add entry %s,"
 
1141
                          " to new ldb file! (%d [%s])\n",
 
1142
                          ldb_dn_get_linearized(msg->dn),
 
1143
                          ret, ldb_errstring(ctx->ldb)));
 
1144
            }
 
1145
 
 
1146
            ret = ldb_delete(ldb, orig_dn);
 
1147
            if (ret != LDB_SUCCESS) {
 
1148
                DEBUG(0, ("WARNING: Could not remove entry %s,"
 
1149
                          " from old ldb file! (%d [%s])\n",
 
1150
                          ldb_dn_get_linearized(orig_dn),
 
1151
                          ret, ldb_errstring(ldb)));
 
1152
            }
 
1153
        }
 
1154
 
 
1155
        /* now remove the basic containers from local */
 
1156
        /* these were optional so debug at level 9 in case
 
1157
         * of failure just for tracing */
 
1158
        ret = ldb_delete(ldb, groups_dn);
 
1159
        if (ret != LDB_SUCCESS) {
 
1160
            DEBUG(9, ("WARNING: Could not remove entry %s,"
 
1161
                      " from old ldb file! (%d [%s])\n",
 
1162
                      ldb_dn_get_linearized(groups_dn),
 
1163
                      ret, ldb_errstring(ldb)));
 
1164
        }
 
1165
        ret = ldb_delete(ldb, users_dn);
 
1166
        if (ret != LDB_SUCCESS) {
 
1167
            DEBUG(9, ("WARNING: Could not remove entry %s,"
 
1168
                      " from old ldb file! (%d [%s])\n",
 
1169
                      ldb_dn_get_linearized(users_dn),
 
1170
                      ret, ldb_errstring(ldb)));
 
1171
        }
 
1172
        ret = ldb_delete(ldb, domain_dn);
 
1173
        if (ret != LDB_SUCCESS) {
 
1174
            DEBUG(9, ("WARNING: Could not remove entry %s,"
 
1175
                      " from old ldb file! (%d [%s])\n",
 
1176
                      ldb_dn_get_linearized(domain_dn),
 
1177
                      ret, ldb_errstring(ldb)));
 
1178
        }
 
1179
 
 
1180
        ret = ldb_transaction_commit(ctx->ldb);
 
1181
        if (ret != LDB_SUCCESS) {
 
1182
            DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
 
1183
            ret = EIO;
 
1184
            goto done;
 
1185
        }
 
1186
        ctx_trans = false;
 
1187
 
 
1188
        talloc_zfree(domain_dn);
 
1189
        talloc_zfree(groups_dn);
 
1190
        talloc_zfree(users_dn);
 
1191
        talloc_zfree(res);
 
1192
    }
 
1193
 
 
1194
    /* conversion done, upgrade version number */
 
1195
    msg = ldb_msg_new(tmp_ctx);
 
1196
    if (!msg) {
 
1197
        ret = ENOMEM;
 
1198
        goto done;
 
1199
    }
 
1200
    msg->dn = ldb_dn_new(tmp_ctx, ldb, "cn=sysdb");
 
1201
    if (!msg->dn) {
 
1202
        ret = ENOMEM;
 
1203
        goto done;
 
1204
    }
 
1205
 
 
1206
    ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL);
 
1207
    if (ret != LDB_SUCCESS) {
 
1208
        ret = ENOMEM;
 
1209
        goto done;
 
1210
    }
 
1211
    ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_3);
 
1212
    if (ret != LDB_SUCCESS) {
 
1213
        ret = ENOMEM;
 
1214
        goto done;
 
1215
    }
 
1216
 
 
1217
    ret = ldb_modify(ldb, msg);
 
1218
    if (ret != LDB_SUCCESS) {
 
1219
        ret = sysdb_error_to_errno(ret);
 
1220
        goto done;
 
1221
    }
 
1222
 
 
1223
    ret = ldb_transaction_commit(ldb);
 
1224
    if (ret != LDB_SUCCESS) {
 
1225
        DEBUG(1, ("Failed to commit ldb transaction! (%d)\n", ret));
 
1226
        ret = EIO;
 
1227
        goto exit;
 
1228
    }
 
1229
 
 
1230
    ret = EOK;
 
1231
 
 
1232
done:
 
1233
    if (ret != EOK) {
 
1234
        if (ctx_trans) {
 
1235
            ret = ldb_transaction_cancel(ctx->ldb);
 
1236
            if (ret != LDB_SUCCESS) {
 
1237
                DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
 
1238
            }
 
1239
        }
 
1240
        ret = ldb_transaction_cancel(ldb);
 
1241
        if (ret != LDB_SUCCESS) {
 
1242
            DEBUG(1, ("Failed to cancel ldb transaction! (%d)\n", ret));
 
1243
        }
 
1244
    }
 
1245
 
 
1246
exit:
 
1247
    talloc_free(tmp_ctx);
 
1248
    return ret;
 
1249
}
 
1250
 
 
1251
static int sysdb_upgrade_03(struct sysdb_ctx *ctx, const char **ver)
 
1252
{
 
1253
    TALLOC_CTX *tmp_ctx;
 
1254
    int ret;
 
1255
    struct ldb_message *msg;
 
1256
 
 
1257
    tmp_ctx = talloc_new(ctx);
 
1258
    if (!tmp_ctx) {
 
1259
        return ENOMEM;
 
1260
    }
 
1261
 
 
1262
    DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_4));
 
1263
 
 
1264
    ret = ldb_transaction_start(ctx->ldb);
 
1265
    if (ret != LDB_SUCCESS) {
 
1266
        ret = EIO;
 
1267
        goto done;
 
1268
    }
 
1269
 
 
1270
    /* Make this database case-sensitive */
 
1271
    msg = ldb_msg_new(tmp_ctx);
 
1272
    if (!msg) {
 
1273
        ret = ENOMEM;
 
1274
        goto done;
 
1275
    }
 
1276
    msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "@ATTRIBUTES");
 
1277
    if (!msg->dn) {
 
1278
        ret = ENOMEM;
 
1279
        goto done;
 
1280
    }
 
1281
 
 
1282
    ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_DELETE, NULL);
 
1283
    if (ret != LDB_SUCCESS) {
 
1284
        ret = ENOMEM;
 
1285
        goto done;
 
1286
    }
 
1287
 
 
1288
    ret = ldb_modify(ctx->ldb, msg);
 
1289
    if (ret != LDB_SUCCESS) {
 
1290
        ret = sysdb_error_to_errno(ret);
 
1291
        goto done;
 
1292
    }
 
1293
 
 
1294
    /* conversion done, upgrade version number */
 
1295
    msg = ldb_msg_new(tmp_ctx);
 
1296
    if (!msg) {
 
1297
        ret = ENOMEM;
 
1298
        goto done;
 
1299
    }
 
1300
    msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb");
 
1301
    if (!msg->dn) {
 
1302
        ret = ENOMEM;
 
1303
        goto done;
 
1304
    }
 
1305
 
 
1306
    ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL);
 
1307
    if (ret != LDB_SUCCESS) {
 
1308
        ret = ENOMEM;
 
1309
        goto done;
 
1310
    }
 
1311
    ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_4);
 
1312
    if (ret != LDB_SUCCESS) {
 
1313
        ret = ENOMEM;
 
1314
        goto done;
 
1315
    }
 
1316
 
 
1317
    ret = ldb_modify(ctx->ldb, msg);
 
1318
    if (ret != LDB_SUCCESS) {
 
1319
        ret = sysdb_error_to_errno(ret);
 
1320
        goto done;
 
1321
    }
 
1322
 
 
1323
    ret = EOK;
 
1324
 
 
1325
done:
 
1326
    talloc_zfree(tmp_ctx);
 
1327
 
 
1328
    if (ret != EOK) {
 
1329
        ret = ldb_transaction_cancel(ctx->ldb);
 
1330
    } else {
 
1331
        ret = ldb_transaction_commit(ctx->ldb);
 
1332
        *ver = SYSDB_VERSION_0_4;
 
1333
    }
 
1334
    if (ret != LDB_SUCCESS) {
 
1335
        ret = EIO;
 
1336
    }
 
1337
 
 
1338
    return ret;
 
1339
}
 
1340
 
 
1341
static int sysdb_upgrade_04(struct sysdb_ctx *ctx, const char **ver)
 
1342
{
 
1343
    TALLOC_CTX *tmp_ctx;
 
1344
    int ret;
 
1345
    struct ldb_message *msg;
 
1346
 
 
1347
    tmp_ctx = talloc_new(ctx);
 
1348
    if (!tmp_ctx) {
 
1349
        return ENOMEM;
 
1350
    }
 
1351
 
 
1352
    DEBUG(0, ("UPGRADING DB TO VERSION %s\n", SYSDB_VERSION_0_5));
 
1353
 
 
1354
    ret = ldb_transaction_start(ctx->ldb);
 
1355
    if (ret != LDB_SUCCESS) {
 
1356
        ret = EIO;
 
1357
        goto done;
 
1358
    }
 
1359
 
 
1360
    /* Add new index */
 
1361
    msg = ldb_msg_new(tmp_ctx);
 
1362
    if (!msg) {
 
1363
        ret = ENOMEM;
 
1364
        goto done;
 
1365
    }
 
1366
    msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "@INDEXLIST");
 
1367
    if (!msg->dn) {
 
1368
        ret = ENOMEM;
 
1369
        goto done;
 
1370
    }
 
1371
 
 
1372
    ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL);
 
1373
    if (ret != LDB_SUCCESS) {
 
1374
        ret = ENOMEM;
 
1375
        goto done;
 
1376
    }
 
1377
    ret = ldb_msg_add_string(msg, "@IDXATTR", "originalDN");
 
1378
    if (ret != LDB_SUCCESS) {
 
1379
        ret = ENOMEM;
 
1380
        goto done;
 
1381
    }
 
1382
 
 
1383
    ret = ldb_modify(ctx->ldb, msg);
 
1384
    if (ret != LDB_SUCCESS) {
 
1385
        ret = sysdb_error_to_errno(ret);
 
1386
        goto done;
 
1387
    }
 
1388
 
 
1389
    /* Rebuild memberuid and memberoif attributes */
 
1390
    msg = ldb_msg_new(tmp_ctx);
 
1391
    if (!msg) {
 
1392
        ret = ENOMEM;
 
1393
        goto done;
 
1394
    }
 
1395
    msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "@MEMBEROF-REBUILD");
 
1396
    if (!msg->dn) {
 
1397
        ret = ENOMEM;
 
1398
        goto done;
 
1399
    }
 
1400
 
 
1401
    ret = ldb_add(ctx->ldb, msg);
 
1402
    if (ret != LDB_SUCCESS) {
 
1403
        ret = sysdb_error_to_errno(ret);
 
1404
        goto done;
 
1405
    }
 
1406
 
 
1407
    /* conversion done, upgrade version number */
 
1408
    msg = ldb_msg_new(tmp_ctx);
 
1409
    if (!msg) {
 
1410
        ret = ENOMEM;
 
1411
        goto done;
 
1412
    }
 
1413
    msg->dn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb");
 
1414
    if (!msg->dn) {
 
1415
        ret = ENOMEM;
 
1416
        goto done;
 
1417
    }
 
1418
 
 
1419
    ret = ldb_msg_add_empty(msg, "version", LDB_FLAG_MOD_REPLACE, NULL);
 
1420
    if (ret != LDB_SUCCESS) {
 
1421
        ret = ENOMEM;
 
1422
        goto done;
 
1423
    }
 
1424
    ret = ldb_msg_add_string(msg, "version", SYSDB_VERSION_0_5);
 
1425
    if (ret != LDB_SUCCESS) {
 
1426
        ret = ENOMEM;
 
1427
        goto done;
 
1428
    }
 
1429
 
 
1430
    ret = ldb_modify(ctx->ldb, msg);
 
1431
    if (ret != LDB_SUCCESS) {
 
1432
        ret = sysdb_error_to_errno(ret);
 
1433
        goto done;
 
1434
    }
 
1435
 
 
1436
    ret = EOK;
 
1437
 
 
1438
done:
 
1439
    talloc_zfree(tmp_ctx);
 
1440
 
 
1441
    if (ret != EOK) {
 
1442
        ret = ldb_transaction_cancel(ctx->ldb);
 
1443
    } else {
 
1444
        ret = ldb_transaction_commit(ctx->ldb);
 
1445
        *ver = SYSDB_VERSION_0_5;
 
1446
    }
 
1447
    if (ret != LDB_SUCCESS) {
 
1448
        ret = EIO;
 
1449
    }
 
1450
 
 
1451
    return ret;
 
1452
}
 
1453
 
 
1454
static int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx,
 
1455
                                      struct sss_domain_info *domain,
 
1456
                                      const char *db_path,
 
1457
                                      bool allow_upgrade,
 
1458
                                      struct sysdb_ctx **_ctx)
 
1459
{
 
1460
    TALLOC_CTX *tmp_ctx = NULL;
 
1461
    struct sysdb_ctx *ctx;
 
1462
    const char *base_ldif;
 
1463
    struct ldb_ldif *ldif;
 
1464
    struct ldb_message *msg;
 
1465
    struct ldb_message_element *el;
 
1466
    struct ldb_result *res;
 
1467
    struct ldb_dn *verdn;
 
1468
    const char *version = NULL;
 
1469
    int ret;
 
1470
 
 
1471
    ctx = talloc_zero(mem_ctx, struct sysdb_ctx);
 
1472
    if (!ctx) {
 
1473
        return ENOMEM;
 
1474
    }
 
1475
    ctx->domain = domain;
 
1476
 
 
1477
    /* The local provider s the only true MPG,
 
1478
     * for the other domains, the provider actually unrolls MPGs */
 
1479
    if (strcasecmp(domain->provider, "local") == 0) {
 
1480
        ctx->mpg = true;
 
1481
    }
 
1482
 
 
1483
    ret = sysdb_get_db_file(ctx, domain->provider,
 
1484
                            domain->name, db_path,
 
1485
                            &ctx->ldb_file);
 
1486
    if (ret != EOK) {
 
1487
        return ret;
 
1488
    }
 
1489
    DEBUG(5, ("DB File for %s: %s\n", domain->name, ctx->ldb_file));
 
1490
 
 
1491
    ret = sysdb_ldb_connect(ctx, ctx->ldb_file, &ctx->ldb);
 
1492
    if (ret != EOK) {
 
1493
        DEBUG(1, ("sysdb_ldb_connect failed.\n"));
 
1494
        return ret;
 
1495
    }
 
1496
 
 
1497
    tmp_ctx = talloc_new(ctx);
 
1498
    if (!tmp_ctx) {
 
1499
        return ENOMEM;
 
1500
    }
 
1501
 
 
1502
    verdn = ldb_dn_new(tmp_ctx, ctx->ldb, "cn=sysdb");
 
1503
    if (!verdn) {
 
1504
        ret = EIO;
 
1505
        goto done;
 
1506
    }
 
1507
 
 
1508
    ret = ldb_search(ctx->ldb, tmp_ctx, &res,
 
1509
                     verdn, LDB_SCOPE_BASE,
 
1510
                     NULL, NULL);
 
1511
    if (ret != LDB_SUCCESS) {
 
1512
        ret = EIO;
 
1513
        goto done;
 
1514
    }
 
1515
    if (res->count > 1) {
 
1516
        ret = EIO;
 
1517
        goto done;
 
1518
    }
 
1519
 
 
1520
    if (res->count == 1) {
 
1521
        el = ldb_msg_find_element(res->msgs[0], "version");
 
1522
        if (el) {
 
1523
            if (el->num_values != 1) {
 
1524
                ret = EINVAL;
 
1525
                goto done;
 
1526
            }
 
1527
            version = talloc_strndup(tmp_ctx,
 
1528
                                     (char *)(el->values[0].data),
 
1529
                                     el->values[0].length);
 
1530
            if (!version) {
 
1531
                ret = ENOMEM;
 
1532
                goto done;
 
1533
            }
 
1534
 
 
1535
            if (strcmp(version, SYSDB_VERSION) == 0) {
 
1536
                /* all fine, return */
 
1537
                ret = EOK;
 
1538
                goto done;
 
1539
            }
 
1540
 
 
1541
            if (!allow_upgrade) {
 
1542
                DEBUG(0, ("Wrong DB version (got %s expected %s)\n",
 
1543
                          version, SYSDB_VERSION));
 
1544
                ret = EINVAL;
 
1545
                goto done;
 
1546
            }
 
1547
 
 
1548
            DEBUG(4, ("Upgrading DB [%s] from version: %s\n",
 
1549
                      domain->name, version));
 
1550
 
 
1551
            if (strcmp(version, SYSDB_VERSION_0_3) == 0) {
 
1552
                ret = sysdb_upgrade_03(ctx, &version);
 
1553
                if (ret != EOK) {
 
1554
                    goto done;
 
1555
                }
 
1556
            }
 
1557
 
 
1558
            if (strcmp(version, SYSDB_VERSION_0_4) == 0) {
 
1559
                ret = sysdb_upgrade_04(ctx, &version);
 
1560
                goto done;
 
1561
            }
 
1562
        }
 
1563
 
 
1564
        DEBUG(0,("Unknown DB version [%s], expected [%s] for domain %s!\n",
 
1565
                 version?version:"not found", SYSDB_VERSION, domain->name));
 
1566
        ret = EINVAL;
 
1567
        goto done;
 
1568
    }
 
1569
 
 
1570
    /* cn=sysdb does not exists, means db is empty, populate */
 
1571
 
 
1572
    base_ldif = SYSDB_BASE_LDIF;
 
1573
    while ((ldif = ldb_ldif_read_string(ctx->ldb, &base_ldif))) {
 
1574
        ret = ldb_add(ctx->ldb, ldif->msg);
 
1575
        if (ret != LDB_SUCCESS) {
 
1576
            DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!\n",
 
1577
                      ret, ldb_errstring(ctx->ldb), domain->name));
 
1578
            ret = EIO;
 
1579
            goto done;
 
1580
        }
 
1581
        ldb_ldif_read_free(ctx->ldb, ldif);
 
1582
    }
 
1583
 
 
1584
    /* == create base domain object == */
 
1585
 
 
1586
    msg = ldb_msg_new(tmp_ctx);
 
1587
    if (!msg) {
 
1588
        ret = ENOMEM;
 
1589
        goto done;
 
1590
    }
 
1591
    msg->dn = ldb_dn_new_fmt(msg, ctx->ldb, SYSDB_DOM_BASE, domain->name);
 
1592
    if (!msg->dn) {
 
1593
        ret = ENOMEM;
 
1594
        goto done;
 
1595
    }
 
1596
    ret = ldb_msg_add_fmt(msg, "cn", "%s", domain->name);
 
1597
    if (ret != LDB_SUCCESS) {
 
1598
        ret = EIO;
 
1599
        goto done;
 
1600
    }
 
1601
    /* do a synchronous add */
 
1602
    ret = ldb_add(ctx->ldb, msg);
 
1603
    if (ret != LDB_SUCCESS) {
 
1604
        DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!\n",
 
1605
                  ret, ldb_errstring(ctx->ldb), domain->name));
 
1606
        ret = EIO;
 
1607
        goto done;
 
1608
    }
 
1609
    talloc_zfree(msg);
 
1610
 
 
1611
    /* == create Users tree == */
 
1612
 
 
1613
    msg = ldb_msg_new(tmp_ctx);
 
1614
    if (!msg) {
 
1615
        ret = ENOMEM;
 
1616
        goto done;
 
1617
    }
 
1618
    msg->dn = ldb_dn_new_fmt(msg, ctx->ldb,
 
1619
                             SYSDB_TMPL_USER_BASE, domain->name);
 
1620
    if (!msg->dn) {
 
1621
        ret = ENOMEM;
 
1622
        goto done;
 
1623
    }
 
1624
    ret = ldb_msg_add_fmt(msg, "cn", "Users");
 
1625
    if (ret != LDB_SUCCESS) {
 
1626
        ret = EIO;
 
1627
        goto done;
 
1628
    }
 
1629
    /* do a synchronous add */
 
1630
    ret = ldb_add(ctx->ldb, msg);
 
1631
    if (ret != LDB_SUCCESS) {
 
1632
        DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!\n",
 
1633
                  ret, ldb_errstring(ctx->ldb), domain->name));
 
1634
        ret = EIO;
 
1635
        goto done;
 
1636
    }
 
1637
    talloc_zfree(msg);
 
1638
 
 
1639
    /* == create Groups tree == */
 
1640
 
 
1641
    msg = ldb_msg_new(tmp_ctx);
 
1642
    if (!msg) {
 
1643
        ret = ENOMEM;
 
1644
        goto done;
 
1645
    }
 
1646
    msg->dn = ldb_dn_new_fmt(msg, ctx->ldb,
 
1647
                             SYSDB_TMPL_GROUP_BASE, domain->name);
 
1648
    if (!msg->dn) {
 
1649
        ret = ENOMEM;
 
1650
        goto done;
 
1651
    }
 
1652
    ret = ldb_msg_add_fmt(msg, "cn", "Groups");
 
1653
    if (ret != LDB_SUCCESS) {
 
1654
        ret = EIO;
 
1655
        goto done;
 
1656
    }
 
1657
    /* do a synchronous add */
 
1658
    ret = ldb_add(ctx->ldb, msg);
 
1659
    if (ret != LDB_SUCCESS) {
 
1660
        DEBUG(0, ("Failed to initialize DB (%d, [%s]) for domain %s!\n",
 
1661
                  ret, ldb_errstring(ctx->ldb), domain->name));
 
1662
        ret = EIO;
 
1663
        goto done;
 
1664
    }
 
1665
    talloc_zfree(msg);
 
1666
 
 
1667
    ret = EOK;
 
1668
 
 
1669
done:
 
1670
    if (ret == EOK) {
 
1671
        *_ctx = ctx;
 
1672
    }
 
1673
    talloc_free(tmp_ctx);
 
1674
    return ret;
 
1675
}
 
1676
 
 
1677
int sysdb_init(TALLOC_CTX *mem_ctx,
 
1678
               struct confdb_ctx *cdb,
 
1679
               const char *alt_db_path,
 
1680
               bool allow_upgrade,
 
1681
               struct sysdb_ctx_list **_ctx_list)
 
1682
{
 
1683
    struct sysdb_ctx_list *ctx_list;
 
1684
    struct sss_domain_info *domains, *dom;
 
1685
    struct sysdb_ctx *ctx;
 
1686
    int ret;
 
1687
 
 
1688
    ctx_list = talloc_zero(mem_ctx, struct sysdb_ctx_list);
 
1689
    if (!ctx_list) {
 
1690
        return ENOMEM;
 
1691
    }
 
1692
 
 
1693
    if (alt_db_path) {
 
1694
        ctx_list->db_path = talloc_strdup(ctx_list, alt_db_path);
 
1695
    } else {
 
1696
        ctx_list->db_path = talloc_strdup(ctx_list, DB_PATH);
 
1697
    }
 
1698
    if (!ctx_list->db_path) {
 
1699
        talloc_zfree(ctx_list);
 
1700
        return ENOMEM;
 
1701
    }
 
1702
 
 
1703
    /* open a db for each backend */
 
1704
    ret = confdb_get_domains(cdb, &domains);
 
1705
    if (ret != EOK) {
 
1706
        talloc_zfree(ctx_list);
 
1707
        return ret;
 
1708
    }
 
1709
 
 
1710
    if (allow_upgrade) {
 
1711
        /* check if we have an old sssd.ldb to upgrade */
 
1712
        ret = sysdb_check_upgrade_02(ctx_list, domains,
 
1713
                                     ctx_list->db_path);
 
1714
        if (ret != EOK) {
 
1715
            talloc_zfree(ctx_list);
 
1716
            return ret;
 
1717
        }
 
1718
    }
 
1719
 
 
1720
    for (dom = domains; dom; dom = dom->next) {
 
1721
 
 
1722
        ctx_list->dbs = talloc_realloc(ctx_list, ctx_list->dbs,
 
1723
                                       struct sysdb_ctx *,
 
1724
                                       ctx_list->num_dbs + 1);
 
1725
        if (!ctx_list->dbs) {
 
1726
            talloc_zfree(ctx_list);
 
1727
            return ENOMEM;
 
1728
        }
 
1729
 
 
1730
        ret = sysdb_domain_init_internal(ctx_list, dom,
 
1731
                                         ctx_list->db_path,
 
1732
                                         allow_upgrade, &ctx);
 
1733
        if (ret != EOK) {
 
1734
            talloc_zfree(ctx_list);
 
1735
            return ret;
 
1736
        }
 
1737
 
 
1738
        ctx_list->dbs[ctx_list->num_dbs] = ctx;
 
1739
        ctx_list->num_dbs++;
 
1740
    }
 
1741
    if (ctx_list->num_dbs == 0) {
 
1742
        /* what? .. */
 
1743
        talloc_zfree(ctx_list);
 
1744
        return ENOENT;
 
1745
    }
 
1746
 
 
1747
    *_ctx_list = ctx_list;
 
1748
 
 
1749
    return EOK;
 
1750
}
 
1751
 
 
1752
int sysdb_domain_init(TALLOC_CTX *mem_ctx,
 
1753
                      struct sss_domain_info *domain,
 
1754
                      const char *db_path,
 
1755
                      struct sysdb_ctx **_ctx)
 
1756
{
 
1757
    return sysdb_domain_init_internal(mem_ctx, domain,
 
1758
                                      db_path, false, _ctx);
 
1759
}
 
1760
 
 
1761
int sysdb_get_ctx_from_list(struct sysdb_ctx_list *ctx_list,
 
1762
                            struct sss_domain_info *domain,
 
1763
                            struct sysdb_ctx **ctx)
 
1764
{
 
1765
    int i;
 
1766
 
 
1767
    for (i = 0; i < ctx_list->num_dbs; i++) {
 
1768
        if (ctx_list->dbs[i]->domain == domain) {
 
1769
            *ctx = ctx_list->dbs[i];
 
1770
            return EOK;
 
1771
        }
 
1772
        if (strcasecmp(ctx_list->dbs[i]->domain->name, domain->name) == 0) {
 
1773
            *ctx = ctx_list->dbs[i];
 
1774
            return EOK;
 
1775
        }
 
1776
    }
 
1777
    /* definitely not found */
 
1778
    return ENOENT;
 
1779
}
 
1780
 
 
1781
 
 
1782
int compare_ldb_dn_comp_num(const void *m1, const void *m2)
 
1783
{
 
1784
    struct ldb_message *msg1 = talloc_get_type(*(void **) discard_const(m1),
 
1785
                                               struct ldb_message);
 
1786
    struct ldb_message *msg2 = talloc_get_type(*(void **) discard_const(m2),
 
1787
                                               struct ldb_message);
 
1788
 
 
1789
    return ldb_dn_get_comp_num(msg2->dn) - ldb_dn_get_comp_num(msg1->dn);
 
1790
}
 
1791
 
 
1792
int sysdb_attrs_replace_name(struct sysdb_attrs *attrs, const char *oldname,
 
1793
                             const char *newname)
 
1794
{
 
1795
    struct ldb_message_element *e = NULL;
 
1796
    int i;
 
1797
    const char *dummy;
 
1798
 
 
1799
    if (attrs == NULL || oldname == NULL || newname == NULL) return EINVAL;
 
1800
 
 
1801
    for (i = 0; i < attrs->num; i++) {
 
1802
        if (strcasecmp(oldname, attrs->a[i].name) == 0) {
 
1803
            e = &(attrs->a[i]);
 
1804
        }
 
1805
        if (strcasecmp(newname, attrs->a[i].name) == 0) {
 
1806
            DEBUG(3, ("New attribute name [%s] already exists.\n", newname));
 
1807
            return EEXIST;
 
1808
        }
 
1809
    }
 
1810
 
 
1811
    if (e != NULL) {
 
1812
        dummy = talloc_strdup(attrs, newname);
 
1813
        if (dummy == NULL) {
 
1814
            DEBUG(1, ("talloc_strdup failed.\n"));
 
1815
            return ENOMEM;
 
1816
        }
 
1817
 
 
1818
        talloc_free(discard_const(e->name));
 
1819
        e->name = dummy;
 
1820
    }
 
1821
 
 
1822
    return EOK;
 
1823
}
 
1824
 
 
1825
/* Search for all incidences of attr_name in a list of
 
1826
 * sysdb_attrs and add their value to a list
 
1827
 *
 
1828
 * TODO: Currently only works for single-valued
 
1829
 * attributes. Multi-valued attributes will return
 
1830
 * only the first entry
 
1831
 */
 
1832
errno_t sysdb_attrs_to_list(TALLOC_CTX *memctx,
 
1833
                            struct sysdb_attrs **attrs,
 
1834
                            int attr_count,
 
1835
                            const char *attr_name,
 
1836
                            char ***_list)
 
1837
{
 
1838
    int attr_idx;
 
1839
    int i;
 
1840
    char **list;
 
1841
    char **tmp_list;
 
1842
    int list_idx;
 
1843
 
 
1844
    *_list = NULL;
 
1845
 
 
1846
    /* Assume that every attrs entry contains the attr_name
 
1847
     * This may waste a little memory if some entries don't
 
1848
     * have the attribute, but it will save us the trouble
 
1849
     * of continuously resizing the array.
 
1850
     */
 
1851
    list = talloc_array(memctx, char *, attr_count+1);
 
1852
    if (!list) {
 
1853
        return ENOMEM;
 
1854
    }
 
1855
 
 
1856
    list_idx = 0;
 
1857
    /* Loop through all entries in attrs */
 
1858
    for (attr_idx = 0; attr_idx < attr_count; attr_idx++) {
 
1859
        /* Examine each attribute within the entry */
 
1860
        for (i = 0; i < attrs[attr_idx]->num; i++) {
 
1861
            if (strcasecmp(attrs[attr_idx]->a[i].name, attr_name) == 0) {
 
1862
                /* Attribute name matches the requested name
 
1863
                 * Copy it to the output list
 
1864
                 */
 
1865
                list[list_idx] = talloc_strdup(
 
1866
                        list,
 
1867
                        (const char *)attrs[attr_idx]->a[i].values[0].data);
 
1868
                if (!list[list_idx]) {
 
1869
                    talloc_free(list);
 
1870
                    return ENOMEM;
 
1871
                }
 
1872
                list_idx++;
 
1873
 
 
1874
                /* We only support single-valued attributes
 
1875
                 * Break here and go on to the next entry
 
1876
                 */
 
1877
                break;
 
1878
            }
 
1879
        }
 
1880
    }
 
1881
 
 
1882
    list[list_idx] = NULL;
 
1883
 
 
1884
    /* if list_idx < attr_count, do a realloc to
 
1885
     * reclaim unused memory
 
1886
     */
 
1887
    if (list_idx < attr_count) {
 
1888
        tmp_list = talloc_realloc(memctx, list, char *, list_idx+1);
 
1889
        if (!tmp_list) {
 
1890
            talloc_zfree(list);
 
1891
            return ENOMEM;
 
1892
        }
 
1893
        list = tmp_list;
 
1894
    }
 
1895
 
 
1896
    *_list = list;
 
1897
    return EOK;
 
1898
}
 
1899
 
 
1900
errno_t sysdb_has_enumerated(struct sysdb_ctx *ctx,
 
1901
                             struct sss_domain_info *dom,
 
1902
                             bool *has_enumerated)
 
1903
{
 
1904
    errno_t ret;
 
1905
    int lret;
 
1906
    struct ldb_dn *base_dn;
 
1907
    struct ldb_result *res;
 
1908
    const char *attributes[2] = {SYSDB_HAS_ENUMERATED,
 
1909
                                 NULL};
 
1910
    TALLOC_CTX *tmpctx;
 
1911
 
 
1912
 
 
1913
    tmpctx = talloc_new(NULL);
 
1914
    if (!tmpctx) {
 
1915
        ret = ENOMEM;
 
1916
        goto done;
 
1917
    }
 
1918
 
 
1919
    base_dn = ldb_dn_new_fmt(tmpctx, ctx->ldb,
 
1920
                             SYSDB_DOM_BASE,
 
1921
                             dom->name);
 
1922
    if (!base_dn) {
 
1923
        ret = ENOMEM;
 
1924
        goto done;
 
1925
    }
 
1926
 
 
1927
    lret = ldb_search(ctx->ldb, tmpctx, &res, base_dn,
 
1928
                      LDB_SCOPE_BASE, attributes, NULL);
 
1929
    if (lret != LDB_SUCCESS) {
 
1930
        ret = sysdb_error_to_errno(lret);
 
1931
        goto done;
 
1932
    }
 
1933
 
 
1934
    if (res->count == 0) {
 
1935
        /* This entry has not been populated in LDB
 
1936
         * This is a common case, as unlike LDAP,
 
1937
         * LDB does not need to have all of its parent
 
1938
         * objects actually exist.
 
1939
         * This object in the sysdb exists mostly just
 
1940
         * to contain this attribute.
 
1941
         */
 
1942
        *has_enumerated = false;
 
1943
        ret = EOK;
 
1944
        goto done;
 
1945
    } else if (res->count != 1) {
 
1946
        DEBUG(0, ("Corrupted database. "
 
1947
                  "More than one entry for base search.\n"));
 
1948
        ret = EIO;
 
1949
        goto done;
 
1950
    }
 
1951
 
 
1952
    /* Object existed. Return the stored value */
 
1953
    *has_enumerated = ldb_msg_find_attr_as_bool(res->msgs[0],
 
1954
                                                SYSDB_HAS_ENUMERATED,
 
1955
                                                false);
 
1956
 
 
1957
    ret = EOK;
 
1958
 
 
1959
done:
 
1960
    talloc_free(tmpctx);
 
1961
    return ret;
 
1962
}
 
1963
 
 
1964
errno_t sysdb_set_enumerated(struct sysdb_ctx *ctx,
 
1965
                             struct sss_domain_info *dom,
 
1966
                             bool enumerated)
 
1967
{
 
1968
    errno_t ret;
 
1969
    int lret;
 
1970
    TALLOC_CTX *tmp_ctx;
 
1971
    struct ldb_message *msg;
 
1972
    struct ldb_result *res;
 
1973
    struct ldb_dn *dn;
 
1974
 
 
1975
    tmp_ctx = talloc_new(NULL);
 
1976
    if (!tmp_ctx) {
 
1977
        ret = ENOMEM;
 
1978
        goto done;
 
1979
    }
 
1980
 
 
1981
    dn = ldb_dn_new_fmt(tmp_ctx, ctx->ldb,
 
1982
                        SYSDB_DOM_BASE,
 
1983
                        dom->name);
 
1984
    if (!dn) {
 
1985
        ret = ENOMEM;
 
1986
        goto done;
 
1987
    }
 
1988
 
 
1989
    lret = ldb_search(ctx->ldb, tmp_ctx, &res,
 
1990
                      dn, LDB_SCOPE_BASE,
 
1991
                      NULL, NULL);
 
1992
    if (lret != LDB_SUCCESS) {
 
1993
        ret = EIO;
 
1994
        goto done;
 
1995
    }
 
1996
 
 
1997
    msg = ldb_msg_new(tmp_ctx);
 
1998
    if (!msg) {
 
1999
        ret = ENOMEM;
 
2000
        goto done;
 
2001
    }
 
2002
    msg->dn = dn;
 
2003
 
 
2004
    if (res->count == 0) {
 
2005
        lret = ldb_msg_add_string(msg, "cn", dom->name);
 
2006
        if (lret != LDB_SUCCESS) {
 
2007
            ret = sysdb_error_to_errno(lret);
 
2008
            goto done;
 
2009
        }
 
2010
    } else if (res->count != 1) {
 
2011
        DEBUG(0, ("Got more than one reply for base search!\n"));
 
2012
        ret = EIO;
 
2013
        goto done;
 
2014
    } else {
 
2015
        lret = ldb_msg_add_empty(msg, SYSDB_HAS_ENUMERATED,
 
2016
                                 LDB_FLAG_MOD_REPLACE, NULL);
 
2017
        if (lret != LDB_SUCCESS) {
 
2018
            ret = sysdb_error_to_errno(lret);
 
2019
            goto done;
 
2020
        }
 
2021
    }
 
2022
    lret = ldb_msg_add_fmt(msg, SYSDB_HAS_ENUMERATED, "%s",
 
2023
                           enumerated?"TRUE":"FALSE");
 
2024
    if (lret != LDB_SUCCESS) {
 
2025
        ret = sysdb_error_to_errno(lret);
 
2026
        goto done;
 
2027
    }
 
2028
 
 
2029
    if (res->count) {
 
2030
        lret = ldb_modify(ctx->ldb, msg);
 
2031
    } else {
 
2032
        lret = ldb_add(ctx->ldb, msg);
 
2033
    }
 
2034
 
 
2035
    ret = sysdb_error_to_errno(lret);
 
2036
 
 
2037
done:
 
2038
    talloc_free(tmp_ctx);
 
2039
    return ret;
 
2040
}
 
2041
 
 
2042
errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb,
 
2043
                                 struct sysdb_attrs *attrs,
 
2044
                                 const char *ldap_attr,
 
2045
                                 const char **_primary)
 
2046
{
 
2047
    errno_t ret;
 
2048
    char *rdn_attr = NULL;
 
2049
    char *rdn_val = NULL;
 
2050
    struct ldb_message_element *sysdb_name_el;
 
2051
    struct ldb_message_element *orig_dn_el;
 
2052
    size_t i;
 
2053
    TALLOC_CTX *tmpctx = NULL;
 
2054
 
 
2055
    tmpctx = talloc_new(NULL);
 
2056
    if (!tmpctx) {
 
2057
        return ENOMEM;
 
2058
    }
 
2059
 
 
2060
    ret = sysdb_attrs_get_el(attrs,
 
2061
                             SYSDB_NAME,
 
2062
                             &sysdb_name_el);
 
2063
    if (sysdb_name_el->num_values == 0) {
 
2064
        ret = EINVAL;
 
2065
        goto done;
 
2066
    }
 
2067
 
 
2068
    if (sysdb_name_el->num_values == 1) {
 
2069
        /* Entry contains only one name. Just return that */
 
2070
        *_primary = (const char *)sysdb_name_el->values[0].data;
 
2071
        ret = EOK;
 
2072
        goto done;
 
2073
    }
 
2074
 
 
2075
    /* Multiple values for name. Check whether one matches the RDN */
 
2076
 
 
2077
    ret = sysdb_attrs_get_el(attrs, SYSDB_ORIG_DN, &orig_dn_el);
 
2078
    if (ret) {
 
2079
        goto done;
 
2080
    }
 
2081
    if (orig_dn_el->num_values == 0) {
 
2082
        DEBUG(1, ("Original DN is not available.\n"));
 
2083
        ret = EINVAL;
 
2084
        goto done;
 
2085
    } else if (orig_dn_el->num_values == 1) {
 
2086
        ret = sysdb_get_rdn(sysdb, tmpctx,
 
2087
                            (const char *) orig_dn_el->values[0].data,
 
2088
                            &rdn_attr,
 
2089
                            &rdn_val);
 
2090
        if (ret != EOK) {
 
2091
            DEBUG(1, ("Could not get rdn from [%s]\n",
 
2092
                      (const char *) orig_dn_el->values[0].data));
 
2093
            goto done;
 
2094
        }
 
2095
    } else {
 
2096
        DEBUG(1, ("Should not have more than one origDN\n"));
 
2097
        ret = EINVAL;
 
2098
        goto done;
 
2099
    }
 
2100
 
 
2101
    /* First check whether the attribute name matches */
 
2102
    DEBUG(8, ("Comparing attribute names [%s] and [%s]\n",
 
2103
              rdn_attr, ldap_attr));
 
2104
    if (strcasecmp(rdn_attr, ldap_attr) != 0) {
 
2105
        /* Multiple entries, and the RDN attribute doesn't match.
 
2106
         * We have no way of resolving this deterministically,
 
2107
         * so we'll punt.
 
2108
         */
 
2109
        DEBUG(1, ("Cannot save entry. It has multiple names and the RDN "
 
2110
                  "attribute does not match\n"));
 
2111
        ret = EINVAL;
 
2112
        goto done;
 
2113
    }
 
2114
 
 
2115
    for (i = 0; i < sysdb_name_el->num_values; i++) {
 
2116
        if (strcasecmp(rdn_val,
 
2117
                       (const char *)sysdb_name_el->values[i].data) == 0) {
 
2118
            /* This name matches the RDN. Use it */
 
2119
            break;
 
2120
        }
 
2121
    }
 
2122
    if (i < sysdb_name_el->num_values) {
 
2123
        /* Match was found */
 
2124
        *_primary = (const char *)sysdb_name_el->values[i].data;
 
2125
    } else {
 
2126
        /* If we can't match the name to the RDN, we just have to
 
2127
         * throw up our hands. There's no deterministic way to
 
2128
         * decide which name is correct.
 
2129
         */
 
2130
        DEBUG(1, ("Cannot save entry. Unable to determine groupname\n"));
 
2131
        ret = EINVAL;
 
2132
        goto done;
 
2133
    }
 
2134
 
 
2135
    ret = EOK;
 
2136
 
 
2137
done:
 
2138
    if (ret != EOK) {
 
2139
        DEBUG(1, ("Could not determine primary name: [%d][%s]\n",
 
2140
                  ret, strerror(ret)));
 
2141
    }
 
2142
    talloc_free(tmpctx);
 
2143
    return ret;
 
2144
}
 
2145
 
 
2146
errno_t sysdb_attrs_primary_name_list(struct sysdb_ctx *sysdb,
 
2147
                                      TALLOC_CTX *mem_ctx,
 
2148
                                      struct sysdb_attrs **attr_list,
 
2149
                                      size_t attr_count,
 
2150
                                      const char *ldap_attr,
 
2151
                                      char ***name_list)
 
2152
{
 
2153
    errno_t ret;
 
2154
    size_t i, j;
 
2155
    char **list;
 
2156
    const char *name;
 
2157
 
 
2158
    /* Assume that every entry has a primary name */
 
2159
    list = talloc_array(mem_ctx, char *, attr_count+1);
 
2160
    if (!list) {
 
2161
        return ENOMEM;
 
2162
    }
 
2163
 
 
2164
    j = 0;
 
2165
    for (i = 0; i < attr_count; i++) {
 
2166
        ret = sysdb_attrs_primary_name(sysdb,
 
2167
                                       attr_list[i],
 
2168
                                       ldap_attr,
 
2169
                                       &name);
 
2170
        if (ret != EOK) {
 
2171
            DEBUG(1, ("Could not determine primary name\n"));
 
2172
            /* Skip and continue. Don't advance 'j' */
 
2173
            continue;
 
2174
        }
 
2175
 
 
2176
        list[j] = talloc_strdup(list, name);
 
2177
        if (!list[j]) {
 
2178
            ret = ENOMEM;
 
2179
            goto done;
 
2180
        }
 
2181
 
 
2182
        j++;
 
2183
    }
 
2184
 
 
2185
    /* NULL-terminate the list */
 
2186
    list[j] = NULL;
 
2187
 
 
2188
    *name_list = list;
 
2189
 
 
2190
    ret = EOK;
 
2191
 
 
2192
done:
 
2193
    if (ret != EOK) {
 
2194
        talloc_free(list);
 
2195
    }
 
2196
    return ret;
 
2197
}