~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/lib/ldb/common/ldb_dn.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   ldb database library
 
3
 
 
4
   Copyright (C) Simo Sorce 2005
 
5
 
 
6
     ** NOTE! The following LGPL license applies to the ldb
 
7
     ** library. This does NOT imply that all of Samba is released
 
8
     ** under the LGPL
 
9
   
 
10
   This library is free software; you can redistribute it and/or
 
11
   modify it under the terms of the GNU Lesser General Public
 
12
   License as published by the Free Software Foundation; either
 
13
   version 3 of the License, or (at your option) any later version.
 
14
 
 
15
   This library is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
   Lesser General Public License for more details.
 
19
 
 
20
   You should have received a copy of the GNU Lesser General Public
 
21
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
/*
 
25
 *  Name: ldb
 
26
 *
 
27
 *  Component: ldb dn creation and manipulation utility functions
 
28
 *
 
29
 *  Description: - explode a dn into it's own basic elements
 
30
 *                 and put them in a structure (only if necessary)
 
31
 *               - manipulate ldb_dn structures
 
32
 *
 
33
 *  Author: Simo Sorce
 
34
 */
 
35
 
 
36
#include "ldb_private.h"
 
37
#include <ctype.h>
 
38
 
 
39
#define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
 
40
 
 
41
#define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)
 
42
 
 
43
/**
 
44
   internal ldb exploded dn structures
 
45
*/
 
46
struct ldb_dn_component {
 
47
 
 
48
        char *name;
 
49
        struct ldb_val value;
 
50
 
 
51
        char *cf_name;
 
52
        struct ldb_val cf_value;
 
53
};
 
54
 
 
55
struct ldb_dn_extended_component {
 
56
 
 
57
        char *name;
 
58
        struct ldb_val value;
 
59
};
 
60
 
 
61
struct ldb_dn {
 
62
 
 
63
        struct ldb_context *ldb;
 
64
 
 
65
        /* Special DNs are always linearized */
 
66
        bool special;
 
67
        bool invalid;
 
68
 
 
69
        bool valid_case;
 
70
 
 
71
        char *linearized;
 
72
        char *extended_linearized;
 
73
        char *casefold;
 
74
 
 
75
        unsigned int comp_num;
 
76
        struct ldb_dn_component *components;
 
77
 
 
78
        unsigned int extended_comp_num;
 
79
        struct ldb_dn_extended_component *extended_components;
 
80
};
 
81
 
 
82
/* strdn may be NULL */
 
83
struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn)
 
84
{
 
85
        struct ldb_dn *dn;
 
86
 
 
87
        if (! ldb) return NULL;
 
88
 
 
89
        dn = talloc_zero(mem_ctx, struct ldb_dn);
 
90
        LDB_DN_NULL_FAILED(dn);
 
91
 
 
92
        dn->ldb = ldb;
 
93
 
 
94
        if (strdn->data && strdn->length) {
 
95
                if (strdn->data[0] == '@') {
 
96
                        dn->special = true;
 
97
                } 
 
98
                dn->extended_linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
 
99
                LDB_DN_NULL_FAILED(dn->extended_linearized);
 
100
        
 
101
                if (strdn->data[0] == '<') {
 
102
                        const char *p_save, *p = dn->extended_linearized;
 
103
                        do {
 
104
                                p_save = p;
 
105
                                p = strstr(p, ">;");
 
106
                                if (p) {
 
107
                                        p = p + 2;
 
108
                                }
 
109
                        } while (p);
 
110
                        
 
111
                        if (p_save == dn->extended_linearized) {
 
112
                                dn->linearized = talloc_strdup(dn, "");
 
113
                        } else {
 
114
                                dn->linearized = talloc_strdup(dn, p_save);
 
115
                        }
 
116
                        LDB_DN_NULL_FAILED(dn->linearized);
 
117
                } else {
 
118
                        dn->linearized = dn->extended_linearized;
 
119
                        dn->extended_linearized = NULL;
 
120
                }
 
121
        } else {
 
122
                dn->linearized = talloc_strdup(dn, "");
 
123
                LDB_DN_NULL_FAILED(dn->linearized);
 
124
        }
 
125
 
 
126
        return dn;
 
127
 
 
128
failed:
 
129
        talloc_free(dn);
 
130
        return NULL;
 
131
}
 
132
 
 
133
/* strdn may be NULL */
 
134
struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
 
135
{
 
136
        struct ldb_val blob;
 
137
        blob.data = strdn;
 
138
        blob.length = strdn ? strlen(strdn) : 0;
 
139
        return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
 
140
}
 
141
 
 
142
struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
 
143
{
 
144
        char *strdn;
 
145
        va_list ap;
 
146
 
 
147
        if ( (! mem_ctx) || (! ldb)) return NULL;
 
148
 
 
149
        va_start(ap, new_fmt);
 
150
        strdn = talloc_vasprintf(mem_ctx, new_fmt, ap);
 
151
        va_end(ap);
 
152
 
 
153
        if (strdn) {
 
154
                struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, strdn);
 
155
                talloc_free(strdn);
 
156
                return dn;
 
157
        }
 
158
        
 
159
        return NULL;
 
160
}
 
161
 
 
162
static int ldb_dn_escape_internal(char *dst, const char *src, int len)
 
163
{
 
164
        const char *p, *s;
 
165
        char *d;
 
166
        int l;
 
167
 
 
168
        p = s = src;
 
169
        d = dst;
 
170
 
 
171
        while (p - src < len) {
 
172
 
 
173
                p += strcspn(p, ",=\n+<>#;\\\"");
 
174
 
 
175
                if (p - src == len) /* found no escapable chars */
 
176
                        break;
 
177
 
 
178
                memcpy(d, s, p - s); /* copy the part of the string before the stop */
 
179
                d += (p - s); /* move to current position */
 
180
 
 
181
                if (*p) { /* it is a normal escapable character */
 
182
                        *d++ = '\\';
 
183
                        *d++ = *p++;
 
184
                } else { /* we have a zero byte in the string */
 
185
                        strncpy(d, "\00", 3); /* escape the zero */
 
186
                        d += 3;
 
187
                        p++; /* skip the zero */
 
188
                }
 
189
                s = p; /* move forward */
 
190
        }
 
191
 
 
192
        /* copy the last part (with zero) and return */
 
193
        l = len - (s - src);
 
194
        memcpy(d, s, l + 1);
 
195
 
 
196
        /* return the length of the resulting string */
 
197
        return (l + (d - dst));
 
198
 
199
 
 
200
char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
 
201
{
 
202
        char *dst;
 
203
 
 
204
        if (!value.length)
 
205
                return NULL;
 
206
 
 
207
        /* allocate destination string, it will be at most 3 times the source */
 
208
        dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
 
209
        if ( ! dst) {
 
210
                talloc_free(dst);
 
211
                return NULL;
 
212
        }
 
213
 
 
214
        ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
 
215
 
 
216
        dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);
 
217
 
 
218
        return dst;
 
219
}
 
220
 
 
221
/*
 
222
  explode a DN string into a ldb_dn structure
 
223
  based on RFC4514 except that we don't support multiple valued RDNs
 
224
*/
 
225
static bool ldb_dn_explode(struct ldb_dn *dn)
 
226
{
 
227
        char *p, *ex_name, *ex_value, *data, *d, *dt, *t;
 
228
        bool trim = false;
 
229
        bool in_extended = false;
 
230
        bool in_ex_name = false;
 
231
        bool in_ex_value = false;
 
232
        bool in_attr = false;
 
233
        bool in_value = false;
 
234
        bool in_quote = false;
 
235
        bool is_oid = false;
 
236
        bool escape = false;
 
237
        unsigned x;
 
238
        int l, ret;
 
239
        char *parse_dn;
 
240
 
 
241
        if ( ! dn || dn->invalid) return false;
 
242
 
 
243
        if (dn->components) {
 
244
                return true;
 
245
        }
 
246
 
 
247
        if (dn->extended_linearized) {
 
248
                parse_dn = dn->extended_linearized;
 
249
        } else {
 
250
                parse_dn = dn->linearized;
 
251
        }
 
252
 
 
253
        if ( ! parse_dn ) {
 
254
                return false;
 
255
        }
 
256
 
 
257
        /* Empty DNs */
 
258
        if (parse_dn[0] == '\0') {
 
259
                return true;
 
260
        }
 
261
 
 
262
        /* Special DNs case */
 
263
        if (dn->special) {
 
264
                return true;
 
265
        }
 
266
 
 
267
        /* make sure we free this if alloced previously before replacing */
 
268
        talloc_free(dn->components);
 
269
 
 
270
        talloc_free(dn->extended_components);
 
271
        dn->extended_components = NULL;
 
272
 
 
273
        /* in the common case we have 3 or more components */
 
274
        /* make sure all components are zeroed, other functions depend on this */
 
275
        dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
 
276
        if ( ! dn->components) {
 
277
                return false;
 
278
        }
 
279
        dn->comp_num = 0;
 
280
 
 
281
        /* Components data space is allocated here once */
 
282
        data = talloc_array(dn->components, char, strlen(parse_dn) + 1);
 
283
        if (!data) {
 
284
                return false;
 
285
        }
 
286
 
 
287
        p = parse_dn;
 
288
        in_extended = true;
 
289
        in_ex_name = false;
 
290
        in_ex_value = false;
 
291
        trim = true;
 
292
        t = NULL;
 
293
        d = dt = data;
 
294
 
 
295
        while (*p) {
 
296
                if (in_extended) {
 
297
 
 
298
                        if (!in_ex_name && !in_ex_value) {
 
299
 
 
300
                                if (p[0] == '<') {
 
301
                                        p++;
 
302
                                        ex_name = d;
 
303
                                        in_ex_name = true;
 
304
                                        continue;
 
305
                                } else if (p[0] == '\0') {
 
306
                                        p++;
 
307
                                        continue;
 
308
                                } else {
 
309
                                        in_extended = false;
 
310
                                        in_attr = true;
 
311
                                        dt = d;
 
312
 
 
313
                                        continue;
 
314
                                }
 
315
                        }
 
316
                        
 
317
                        if (in_ex_name && *p == '=') {
 
318
                                *d++ = '\0';
 
319
                                p++;
 
320
                                ex_value = d;
 
321
                                in_ex_name = false;
 
322
                                in_ex_value = true;
 
323
                                continue;
 
324
                        }
 
325
 
 
326
                        if (in_ex_value && *p == '>') {
 
327
                                const struct ldb_dn_extended_syntax *extended_syntax;
 
328
                                struct ldb_val ex_val = {
 
329
                                        .data = ex_value,
 
330
                                        .length = d - ex_value
 
331
                                };
 
332
                                        
 
333
                                *d++ = '\0';
 
334
                                p++;
 
335
                                in_ex_value = false;
 
336
 
 
337
                                /* Process name and ex_value */
 
338
 
 
339
                                dn->extended_components = talloc_realloc(dn,
 
340
                                                                         dn->extended_components,
 
341
                                                                         struct ldb_dn_extended_component,
 
342
                                                                         dn->extended_comp_num + 1);
 
343
                                if ( ! dn->extended_components) {
 
344
                                        /* ouch ! */
 
345
                                        goto failed;
 
346
                                }
 
347
 
 
348
                                extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
 
349
                                if (!extended_syntax) {
 
350
                                        /* We don't know about this type of extended DN */
 
351
                                        goto failed;
 
352
                                }
 
353
 
 
354
                                dn->extended_components[dn->extended_comp_num].name = talloc_strdup(dn->extended_components, ex_name);
 
355
                                if (!dn->extended_components[dn->extended_comp_num].name) {
 
356
                                        /* ouch */
 
357
                                        goto failed;
 
358
                                }
 
359
                                ret = extended_syntax->read_fn(dn->ldb, dn->extended_components,
 
360
                                                               &ex_val, &dn->extended_components[dn->extended_comp_num].value);
 
361
                                if (ret != LDB_SUCCESS) {
 
362
                                        dn->invalid = true;
 
363
                                        goto failed;
 
364
                                }
 
365
 
 
366
                                dn->extended_comp_num++;
 
367
 
 
368
                                if (*p == '\0') {
 
369
                                        /* We have reached the end (extended component only)! */
 
370
                                        talloc_free(data);
 
371
                                        return true;
 
372
 
 
373
                                } else if (*p == ';') {
 
374
                                        p++;
 
375
                                        continue;
 
376
                                } else {
 
377
                                        dn->invalid = true;
 
378
                                        goto failed;
 
379
                                }
 
380
                        }
 
381
 
 
382
                        *d++ = *p++;
 
383
                        continue;
 
384
                }
 
385
                if (in_attr) {
 
386
                        if (trim) {
 
387
                                if (*p == ' ') {
 
388
                                        p++;
 
389
                                        continue;
 
390
                                }
 
391
 
 
392
                                /* first char */
 
393
                                trim = false;
 
394
 
 
395
                                if (!isascii(*p)) {
 
396
                                        /* attr names must be ascii only */
 
397
                                        dn->invalid = true;
 
398
                                        goto failed;
 
399
                                }
 
400
 
 
401
                                if (isdigit(*p)) {
 
402
                                        is_oid = true;
 
403
                                } else
 
404
                                if ( ! isalpha(*p)) {
 
405
                                        /* not a digit nor an alpha, invalid attribute name */
 
406
                                        dn->invalid = true;
 
407
                                        goto failed;
 
408
                                }
 
409
                                
 
410
                                /* Copy this character across from parse_dn, now we have trimmed out spaces */
 
411
                                *d++ = *p++;
 
412
                                continue;
 
413
                        }
 
414
 
 
415
                        if (*p == ' ') {
 
416
                                p++;
 
417
                                /* valid only if we are at the end */
 
418
                                trim = true;
 
419
                                continue;
 
420
                        }
 
421
 
 
422
                        if (trim && (*p != '=')) {
 
423
                                /* spaces/tabs are not allowed in attribute names */
 
424
                                dn->invalid = true;
 
425
                                goto failed;
 
426
                        }
 
427
 
 
428
                        if (*p == '=') {
 
429
                                /* attribute terminated */
 
430
                                in_attr = false;
 
431
                                in_value = true;
 
432
                                trim = true;
 
433
                                l = 0;
 
434
 
 
435
                                /* Terminate this string in d (which is a copy of parse_dn with spaces trimmed) */
 
436
                                *d++ = '\0';
 
437
                                dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
 
438
                                if ( ! dn->components[dn->comp_num].name) {
 
439
                                        /* ouch */
 
440
                                        goto failed;
 
441
                                }
 
442
 
 
443
                                dt = d;
 
444
 
 
445
                                p++;
 
446
                                continue;
 
447
                        }
 
448
 
 
449
                        if (!isascii(*p)) {
 
450
                                /* attr names must be ascii only */
 
451
                                dn->invalid = true;
 
452
                                goto failed;
 
453
                        }
 
454
 
 
455
                        if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
 
456
                                /* not a digit nor a dot, invalid attribute oid */
 
457
                                dn->invalid = true;
 
458
                                goto failed;
 
459
                        } else
 
460
                        if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
 
461
                                /* not ALPHA, DIGIT or HYPHEN */
 
462
                                dn->invalid = true;
 
463
                                goto failed;
 
464
                        }
 
465
 
 
466
                        *d++ = *p++;
 
467
                        continue;
 
468
                }
 
469
 
 
470
                if (in_value) {
 
471
                        if (in_quote) {
 
472
                                if (*p == '\"') {
 
473
                                        if (p[-1] != '\\') {
 
474
                                                p++;
 
475
                                                in_quote = false;
 
476
                                                continue;
 
477
                                        }
 
478
                                }
 
479
                                *d++ = *p++;
 
480
                                l++;
 
481
                                continue;
 
482
                        }
 
483
 
 
484
                        if (trim) {
 
485
                                if (*p == ' ') {
 
486
                                        p++;
 
487
                                        continue;
 
488
                                }
 
489
 
 
490
                                /* first char */
 
491
                                trim = false;
 
492
 
 
493
                                if (*p == '\"') {
 
494
                                        in_quote = true;
 
495
                                        p++;
 
496
                                        continue;
 
497
                                }
 
498
                        }
 
499
 
 
500
                        switch (*p) {
 
501
 
 
502
                        /* TODO: support ber encoded values
 
503
                        case '#':
 
504
                        */
 
505
 
 
506
                        case ',':
 
507
                                if (escape) {
 
508
                                        *d++ = *p++;
 
509
                                        l++;
 
510
                                        escape = false;
 
511
                                        continue;
 
512
                                }
 
513
                                /* ok found value terminator */
 
514
 
 
515
                                if ( t ) {
 
516
                                        /* trim back */
 
517
                                        d -= (p - t);
 
518
                                        l -= (p - t);
 
519
                                }
 
520
 
 
521
                                in_attr = true;
 
522
                                in_value = false;
 
523
                                trim = true;
 
524
 
 
525
                                p++;
 
526
                                *d++ = '\0';
 
527
                                dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
 
528
                                dn->components[dn->comp_num].value.length = l;
 
529
                                if ( ! dn->components[dn->comp_num].value.data) {
 
530
                                        /* ouch ! */
 
531
                                        goto failed;
 
532
                                }
 
533
 
 
534
                                dt = d;
 
535
 
 
536
                                dn->comp_num++;
 
537
                                if (dn->comp_num > 2) {
 
538
                                        dn->components = talloc_realloc(dn,
 
539
                                                                        dn->components,
 
540
                                                                        struct ldb_dn_component,
 
541
                                                                        dn->comp_num + 1);
 
542
                                        if ( ! dn->components) {
 
543
                                                /* ouch ! */
 
544
                                                goto failed;
 
545
                                        }
 
546
                                        /* make sure all components are zeroed, other functions depend on this */
 
547
                                        memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component));
 
548
                                }
 
549
 
 
550
                                continue;
 
551
 
 
552
                        case '=':
 
553
                        case '\n':
 
554
                        case '+':
 
555
                        case '<':
 
556
                        case '>':
 
557
                        case '#':
 
558
                        case ';':
 
559
                        case '\"':
 
560
                                /* a string with not escaped specials is invalid (tested) */
 
561
                                if ( ! escape) {
 
562
                                        dn->invalid = true;
 
563
                                        goto failed;
 
564
                                }
 
565
                                escape = false;
 
566
 
 
567
                                *d++ = *p++;
 
568
                                l++;
 
569
 
 
570
                                if ( t ) t = NULL;
 
571
                                break;
 
572
 
 
573
                        case '\\':
 
574
                                if ( ! escape) {
 
575
                                        escape = true;
 
576
                                        p++;
 
577
                                        continue;
 
578
                                }
 
579
                                escape = false;
 
580
 
 
581
                                *d++ = *p++;
 
582
                                l++;
 
583
 
 
584
                                if ( t ) t = NULL;
 
585
                                break;
 
586
 
 
587
                        default:
 
588
                                if (escape) {
 
589
                                        if (sscanf(p, "%02x", &x) != 1) {
 
590
                                                /* invalid escaping sequence */
 
591
                                                dn->invalid = true;
 
592
                                                goto failed;
 
593
                                        }
 
594
                                        escape = false;
 
595
 
 
596
                                        p += 2;
 
597
                                        *d++ = (unsigned char)x;
 
598
                                        l++;
 
599
 
 
600
                                        if ( t ) t = NULL;
 
601
                                        break;
 
602
                                }
 
603
 
 
604
                                if (*p == ' ') { 
 
605
                                        if ( ! t) t = p;
 
606
                                } else {
 
607
                                        if ( t ) t = NULL;
 
608
                                }
 
609
 
 
610
                                *d++ = *p++;
 
611
                                l++;
 
612
                                
 
613
                                break;
 
614
                        }
 
615
 
 
616
                }
 
617
        }
 
618
 
 
619
        if (in_attr || in_quote) {
 
620
                /* invalid dn */
 
621
                dn->invalid = true;
 
622
                goto failed;
 
623
        }
 
624
 
 
625
        /* save last element */
 
626
        if ( t ) {
 
627
                /* trim back */
 
628
                d -= (p - t);
 
629
                l -= (p - t);
 
630
        }
 
631
 
 
632
        *d++ = '\0';
 
633
        dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
 
634
        dn->components[dn->comp_num].value.length = l;
 
635
 
 
636
        if ( ! dn->components[dn->comp_num].value.data) {
 
637
                /* ouch */
 
638
                goto failed;
 
639
        }
 
640
 
 
641
        dn->comp_num++;
 
642
 
 
643
        talloc_free(data);
 
644
        return true;
 
645
 
 
646
failed:
 
647
        dn->comp_num = 0;
 
648
        talloc_free(dn->components);
 
649
        return false;
 
650
}
 
651
 
 
652
bool ldb_dn_validate(struct ldb_dn *dn)
 
653
{
 
654
        return ldb_dn_explode(dn);
 
655
}
 
656
 
 
657
const char *ldb_dn_get_linearized(struct ldb_dn *dn)
 
658
{
 
659
        int i, len;
 
660
        char *d, *n;
 
661
 
 
662
        if ( ! dn || ( dn->invalid)) return NULL;
 
663
 
 
664
        if (dn->linearized) return dn->linearized;
 
665
 
 
666
        if ( ! dn->components) {
 
667
                dn->invalid = true;
 
668
                return NULL;
 
669
        }
 
670
 
 
671
        if (dn->comp_num == 0) {
 
672
                dn->linearized = talloc_strdup(dn, "");
 
673
                if ( ! dn->linearized) return NULL;
 
674
                return dn->linearized;
 
675
        }
 
676
 
 
677
        /* calculate maximum possible length of DN */
 
678
        for (len = 0, i = 0; i < dn->comp_num; i++) {
 
679
                len += strlen(dn->components[i].name); /* name len */
 
680
                len += (dn->components[i].value.length * 3); /* max escaped data len */
 
681
                len += 2; /* '=' and ',' */
 
682
        }
 
683
        dn->linearized = talloc_array(dn, char, len);
 
684
        if ( ! dn->linearized) return NULL;
 
685
 
 
686
        d = dn->linearized;
 
687
 
 
688
        for (i = 0; i < dn->comp_num; i++) {
 
689
 
 
690
                /* copy the name */
 
691
                n = dn->components[i].name;
 
692
                while (*n) *d++ = *n++;
 
693
 
 
694
                *d++ = '=';
 
695
 
 
696
                /* and the value */
 
697
                d += ldb_dn_escape_internal( d,
 
698
                                (char *)dn->components[i].value.data,
 
699
                                dn->components[i].value.length);
 
700
                *d++ = ',';
 
701
        }
 
702
 
 
703
        *(--d) = '\0';
 
704
 
 
705
        /* don't waste more memory than necessary */
 
706
        dn->linearized = talloc_realloc(dn, dn->linearized, char, (d - dn->linearized + 1));
 
707
 
 
708
        return dn->linearized;
 
709
}
 
710
 
 
711
char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
 
712
{
 
713
        const char *linearized = ldb_dn_get_linearized(dn);
 
714
        char *p;
 
715
        int i;
 
716
 
 
717
        if (!linearized) {
 
718
                return NULL;
 
719
        }
 
720
 
 
721
        if (!ldb_dn_has_extended(dn)) {
 
722
                return talloc_strdup(mem_ctx, linearized);
 
723
        }
 
724
        
 
725
        if (!ldb_dn_validate(dn)) {
 
726
                return NULL;
 
727
        }
 
728
 
 
729
        for (i=0; i < dn->extended_comp_num; i++) {
 
730
                struct ldb_val val;
 
731
                int ret;
 
732
                const struct ldb_dn_extended_syntax *extended_syntax;
 
733
                const char *name = dn->extended_components[i].name;
 
734
                
 
735
                extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
 
736
 
 
737
                if (mode == 1) {
 
738
                        ret = extended_syntax->write_clear_fn(dn->ldb, mem_ctx,
 
739
                                                              &dn->extended_components[i].value,
 
740
                                                              &val);
 
741
                } else if (mode == 0) {
 
742
                        ret = extended_syntax->write_hex_fn(dn->ldb, mem_ctx,
 
743
                                                              &dn->extended_components[i].value,
 
744
                                                              &val);
 
745
                } else {
 
746
                        ret = -1;
 
747
                }
 
748
 
 
749
                if (ret != LDB_SUCCESS) {
 
750
                        return NULL;
 
751
                }
 
752
 
 
753
                if (i == 0) {
 
754
                        p = talloc_asprintf(mem_ctx, "<%s=%s>", dn->extended_components[i].name, val.data);
 
755
                } else {
 
756
                        p = talloc_asprintf_append(p, ";<%s=%s>",  dn->extended_components[i].name, val.data);
 
757
                }
 
758
 
 
759
                talloc_free(val.data);
 
760
 
 
761
                if (!p) {
 
762
                        return NULL;
 
763
                }
 
764
        }
 
765
 
 
766
        if (dn->extended_comp_num && *linearized) {
 
767
                p = talloc_asprintf_append(p, ";%s", linearized);
 
768
        }
 
769
 
 
770
        if (!p) {
 
771
                return NULL;
 
772
        }
 
773
 
 
774
        return p;
 
775
}
 
776
 
 
777
 
 
778
 
 
779
char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
 
780
{
 
781
        return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
 
782
}
 
783
 
 
784
/*
 
785
  casefold a dn. We need to casefold the attribute names, and canonicalize 
 
786
  attribute values of case insensitive attributes.
 
787
*/
 
788
 
 
789
static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
 
790
{
 
791
        int i, ret;
 
792
 
 
793
        if ( ! dn || dn->invalid) return false;
 
794
 
 
795
        if (dn->valid_case) return true;
 
796
 
 
797
        if (( ! dn->components) && ( ! ldb_dn_explode(dn))) {
 
798
                return false;
 
799
        }
 
800
 
 
801
        for (i = 0; i < dn->comp_num; i++) {
 
802
                const struct ldb_schema_attribute *a;
 
803
 
 
804
                dn->components[i].cf_name = ldb_attr_casefold(dn->components, dn->components[i].name);
 
805
                if (!dn->components[i].cf_name) {
 
806
                        goto failed;
 
807
                }
 
808
 
 
809
                a = ldb_schema_attribute_by_name(dn->ldb, dn->components[i].cf_name);
 
810
                ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,
 
811
                                                 &(dn->components[i].value),
 
812
                                                 &(dn->components[i].cf_value));
 
813
                if (ret != 0) {
 
814
                        goto failed;
 
815
                }
 
816
        }
 
817
 
 
818
        dn->valid_case = true;
 
819
 
 
820
        return true;
 
821
 
 
822
failed:
 
823
        for (i = 0; i < dn->comp_num; i++) {
 
824
                LDB_FREE(dn->components[i].cf_name);
 
825
                LDB_FREE(dn->components[i].cf_value.data);
 
826
        }
 
827
        return false;
 
828
}
 
829
 
 
830
const char *ldb_dn_get_casefold(struct ldb_dn *dn)
 
831
{
 
832
        int i, len;
 
833
        char *d, *n;
 
834
 
 
835
        if (dn->casefold) return dn->casefold;
 
836
 
 
837
        if (dn->special) { 
 
838
                dn->casefold = talloc_strdup(dn, dn->linearized);
 
839
                if (!dn->casefold) return NULL;
 
840
                dn->valid_case = true;
 
841
                return dn->casefold;
 
842
        }
 
843
 
 
844
        if ( ! ldb_dn_casefold_internal(dn)) {
 
845
                return NULL;
 
846
        }
 
847
 
 
848
        if (dn->comp_num == 0) {
 
849
                if (dn->linearized && dn->linearized[0] == '\0') {
 
850
                        /* hmm a NULL dn, should we faild casefolding ? */
 
851
                        dn->casefold = talloc_strdup(dn, "");
 
852
                        return dn->casefold;
 
853
                }
 
854
                /* A DN must be NULL, special, or have components */
 
855
                dn->invalid = true;
 
856
                return NULL;
 
857
        }
 
858
 
 
859
        /* calculate maximum possible length of DN */
 
860
        for (len = 0, i = 0; i < dn->comp_num; i++) {
 
861
                len += strlen(dn->components[i].cf_name); /* name len */
 
862
                len += (dn->components[i].cf_value.length * 3); /* max escaped data len */
 
863
                len += 2; /* '=' and ',' */
 
864
        }
 
865
        dn->casefold = talloc_array(dn, char, len);
 
866
        if ( ! dn->casefold) return NULL;
 
867
 
 
868
        d = dn->casefold;
 
869
 
 
870
        for (i = 0; i < dn->comp_num; i++) {
 
871
 
 
872
                /* copy the name */
 
873
                n = dn->components[i].cf_name;
 
874
                while (*n) *d++ = *n++;
 
875
 
 
876
                *d++ = '=';
 
877
 
 
878
                /* and the value */
 
879
                d += ldb_dn_escape_internal( d,
 
880
                                (char *)dn->components[i].cf_value.data,
 
881
                                dn->components[i].cf_value.length);
 
882
                *d++ = ',';
 
883
        }
 
884
        *(--d) = '\0';
 
885
 
 
886
        /* don't waste more memory than necessary */
 
887
        dn->casefold = talloc_realloc(dn, dn->casefold, char, strlen(dn->casefold) + 1);
 
888
 
 
889
        return dn->casefold;
 
890
}
 
891
 
 
892
char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
 
893
{
 
894
        return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));
 
895
}
 
896
 
 
897
/* Determine if dn is below base, in the ldap tree.  Used for
 
898
 * evaluating a subtree search.
 
899
 * 0 if they match, otherwise non-zero
 
900
 */
 
901
 
 
902
int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
 
903
{
 
904
        int ret;
 
905
        int n_base, n_dn;
 
906
 
 
907
        if ( ! base || base->invalid) return 1;
 
908
        if ( ! dn || dn->invalid) return -1;
 
909
 
 
910
        if (( ! base->valid_case) || ( ! dn->valid_case)) {
 
911
                if (base->linearized && dn->linearized) {
 
912
                        /* try with a normal compare first, if we are lucky
 
913
                         * we will avoid exploding and casfolding */
 
914
                        int dif;
 
915
                        dif = strlen(dn->linearized) - strlen(base->linearized);
 
916
                        if (dif < 0) return dif;
 
917
                        if (strcmp(base->linearized, &dn->linearized[dif]) == 0) return 0;
 
918
                }
 
919
 
 
920
                if ( ! ldb_dn_casefold_internal(base)) {
 
921
                        return 1;
 
922
                }
 
923
 
 
924
                if ( ! ldb_dn_casefold_internal(dn)) {
 
925
                        return -1;
 
926
                }
 
927
 
 
928
        }
 
929
 
 
930
        /* if base has more components,
 
931
         * they don't have the same base */
 
932
        if (base->comp_num > dn->comp_num) {
 
933
                return (dn->comp_num - base->comp_num);
 
934
        }
 
935
 
 
936
        if (dn->comp_num == 0) {
 
937
                if (dn->special && base->special) {
 
938
                        return strcmp(base->linearized, dn->linearized);
 
939
                } else if (dn->special) {
 
940
                        return -1;
 
941
                } else if (base->special) {
 
942
                        return 1;
 
943
                } else {
 
944
                        return 0;
 
945
                }
 
946
        }
 
947
 
 
948
        n_base = base->comp_num - 1;
 
949
        n_dn = dn->comp_num - 1;
 
950
 
 
951
        while (n_base >= 0) {
 
952
                /* compare attr names */
 
953
                ret = strcmp(base->components[n_base].cf_name, dn->components[n_dn].cf_name);
 
954
                if (ret != 0) return ret;
 
955
 
 
956
                /* compare attr.cf_value. */ 
 
957
                if (base->components[n_base].cf_value.length != dn->components[n_dn].cf_value.length) {
 
958
                        return base->components[n_base].cf_value.length - dn->components[n_dn].cf_value.length;
 
959
                }
 
960
                ret = strcmp((char *)base->components[n_base].cf_value.data, (char *)dn->components[n_dn].cf_value.data);
 
961
                if (ret != 0) return ret;
 
962
 
 
963
                n_base--;
 
964
                n_dn--;
 
965
        }
 
966
 
 
967
        return 0;
 
968
}
 
969
 
 
970
/* compare DNs using casefolding compare functions.  
 
971
 
 
972
   If they match, then return 0
 
973
 */
 
974
 
 
975
int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
 
976
{
 
977
        int i, ret;
 
978
 
 
979
        if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) return -1;
 
980
 
 
981
        if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
 
982
                if (dn0->linearized && dn1->linearized) {
 
983
                        /* try with a normal compare first, if we are lucky
 
984
                         * we will avoid exploding and casfolding */
 
985
                        if (strcmp(dn0->linearized, dn1->linearized) == 0) return 0;
 
986
                }
 
987
 
 
988
                if ( ! ldb_dn_casefold_internal(dn0)) {
 
989
                        return 1;
 
990
                }
 
991
 
 
992
                if ( ! ldb_dn_casefold_internal(dn1)) {
 
993
                        return -1;
 
994
                }
 
995
 
 
996
        }
 
997
 
 
998
        if (dn0->comp_num != dn1->comp_num) {
 
999
                return (dn1->comp_num - dn0->comp_num);
 
1000
        }
 
1001
 
 
1002
        if (dn0->comp_num == 0) {
 
1003
                if (dn0->special && dn1->special) {
 
1004
                        return strcmp(dn0->linearized, dn1->linearized);
 
1005
                } else if (dn0->special) {
 
1006
                        return 1;
 
1007
                } else if (dn1->special) {
 
1008
                        return -1;
 
1009
                } else {
 
1010
                        return 0;
 
1011
                }
 
1012
        }
 
1013
 
 
1014
        for (i = 0; i < dn0->comp_num; i++) {
 
1015
                /* compare attr names */
 
1016
                ret = strcmp(dn0->components[i].cf_name, dn1->components[i].cf_name);
 
1017
                if (ret != 0) return ret;
 
1018
 
 
1019
                /* compare attr.cf_value. */ 
 
1020
                if (dn0->components[i].cf_value.length != dn1->components[i].cf_value.length) {
 
1021
                        return dn0->components[i].cf_value.length - dn1->components[i].cf_value.length;
 
1022
                }
 
1023
                ret = strcmp((char *)dn0->components[i].cf_value.data, (char *)dn1->components[i].cf_value.data);
 
1024
                if (ret != 0) return ret;
 
1025
        }
 
1026
 
 
1027
        return 0;
 
1028
}
 
1029
 
 
1030
static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
 
1031
{
 
1032
        struct ldb_dn_component dst;
 
1033
 
 
1034
        memset(&dst, 0, sizeof(dst));
 
1035
 
 
1036
        if (src == NULL) {
 
1037
                return dst;
 
1038
        }
 
1039
 
 
1040
        dst.value = ldb_val_dup(mem_ctx, &(src->value));
 
1041
        if (dst.value.data == NULL) {
 
1042
                return dst;
 
1043
        }
 
1044
 
 
1045
        dst.name = talloc_strdup(mem_ctx, src->name);
 
1046
        if (dst.name == NULL) {
 
1047
                LDB_FREE(dst.value.data);
 
1048
                return dst;
 
1049
        }
 
1050
 
 
1051
        if (src->cf_value.data) {
 
1052
                dst.cf_value = ldb_val_dup(mem_ctx, &(src->cf_value));
 
1053
                if (dst.cf_value.data == NULL) {
 
1054
                        LDB_FREE(dst.value.data);
 
1055
                        LDB_FREE(dst.name);
 
1056
                        return dst;
 
1057
                }
 
1058
 
 
1059
                dst.cf_name = talloc_strdup(mem_ctx, src->cf_name);
 
1060
                if (dst.cf_name == NULL) {
 
1061
                        LDB_FREE(dst.cf_name);
 
1062
                        LDB_FREE(dst.value.data);
 
1063
                        LDB_FREE(dst.name);
 
1064
                        return dst;
 
1065
                }
 
1066
        } else {
 
1067
                dst.cf_value.data = NULL;
 
1068
                dst.cf_name = NULL;
 
1069
        }
 
1070
 
 
1071
        return dst;
 
1072
}
 
1073
 
 
1074
static struct ldb_dn_extended_component ldb_dn_extended_copy_component(void *mem_ctx, struct ldb_dn_extended_component *src)
 
1075
{
 
1076
        struct ldb_dn_extended_component dst;
 
1077
 
 
1078
        memset(&dst, 0, sizeof(dst));
 
1079
 
 
1080
        if (src == NULL) {
 
1081
                return dst;
 
1082
        }
 
1083
 
 
1084
        dst.value = ldb_val_dup(mem_ctx, &(src->value));
 
1085
        if (dst.value.data == NULL) {
 
1086
                return dst;
 
1087
        }
 
1088
 
 
1089
        dst.name = talloc_strdup(mem_ctx, src->name);
 
1090
        if (dst.name == NULL) {
 
1091
                LDB_FREE(dst.value.data);
 
1092
                return dst;
 
1093
        }
 
1094
 
 
1095
        return dst;
 
1096
}
 
1097
 
 
1098
struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
 
1099
{
 
1100
        struct ldb_dn *new_dn;
 
1101
 
 
1102
        if (!dn || dn->invalid) {
 
1103
                return NULL;
 
1104
        }
 
1105
 
 
1106
        new_dn = talloc_zero(mem_ctx, struct ldb_dn);
 
1107
        if ( !new_dn) {
 
1108
                return NULL;
 
1109
        }
 
1110
 
 
1111
        *new_dn = *dn;
 
1112
 
 
1113
        if (dn->components) {
 
1114
                int i;
 
1115
 
 
1116
                new_dn->components = talloc_zero_array(new_dn, struct ldb_dn_component, dn->comp_num);
 
1117
                if ( ! new_dn->components) {
 
1118
                        talloc_free(new_dn);
 
1119
                        return NULL;
 
1120
                }
 
1121
 
 
1122
                for (i = 0; i < dn->comp_num; i++) {
 
1123
                        new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &dn->components[i]);
 
1124
                        if ( ! new_dn->components[i].value.data) {
 
1125
                                talloc_free(new_dn);
 
1126
                                return NULL;
 
1127
                        }
 
1128
                }
 
1129
        }
 
1130
 
 
1131
        if (dn->extended_components) {
 
1132
                int i;
 
1133
 
 
1134
                new_dn->extended_components = talloc_zero_array(new_dn, struct ldb_dn_extended_component, dn->extended_comp_num);
 
1135
                if ( ! new_dn->extended_components) {
 
1136
                        talloc_free(new_dn);
 
1137
                        return NULL;
 
1138
                }
 
1139
 
 
1140
                for (i = 0; i < dn->extended_comp_num; i++) {
 
1141
                        new_dn->extended_components[i] = ldb_dn_extended_copy_component(new_dn->extended_components, &dn->extended_components[i]);
 
1142
                        if ( ! new_dn->extended_components[i].value.data) {
 
1143
                                talloc_free(new_dn);
 
1144
                                return NULL;
 
1145
                        }
 
1146
                }
 
1147
        }
 
1148
 
 
1149
        if (dn->casefold) {
 
1150
                new_dn->casefold = talloc_strdup(new_dn, dn->casefold);
 
1151
                if ( ! new_dn->casefold) {
 
1152
                        talloc_free(new_dn);
 
1153
                        return NULL;
 
1154
                }
 
1155
        }
 
1156
 
 
1157
        if (dn->linearized) {
 
1158
                new_dn->linearized = talloc_strdup(new_dn, dn->linearized);
 
1159
                if ( ! new_dn->linearized) {
 
1160
                        talloc_free(new_dn);
 
1161
                        return NULL;
 
1162
                }
 
1163
        }
 
1164
 
 
1165
        if (dn->extended_linearized) {
 
1166
                new_dn->extended_linearized = talloc_strdup(new_dn, dn->extended_linearized);
 
1167
                if ( ! new_dn->extended_linearized) {
 
1168
                        talloc_free(new_dn);
 
1169
                        return NULL;
 
1170
                }
 
1171
        }
 
1172
 
 
1173
        return new_dn;
 
1174
}
 
1175
 
 
1176
/* modify the given dn by adding a base.
 
1177
 *
 
1178
 * return true if successful and false if not
 
1179
 * if false is returned the dn may be marked invalid
 
1180
 */
 
1181
bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
 
1182
{
 
1183
        const char *s;
 
1184
        char *t;
 
1185
 
 
1186
        if ( !base || base->invalid || !dn || dn->invalid) {
 
1187
                return false;
 
1188
        }
 
1189
 
 
1190
        if (dn->components) {
 
1191
                int i;
 
1192
 
 
1193
                if ( ! ldb_dn_validate(base)) {
 
1194
                        return false;
 
1195
                }
 
1196
 
 
1197
                s = NULL;
 
1198
                if (dn->valid_case) {
 
1199
                        if ( ! (s = ldb_dn_get_casefold(base))) {
 
1200
                                return false;
 
1201
                        }
 
1202
                }
 
1203
 
 
1204
                dn->components = talloc_realloc(dn,
 
1205
                                                dn->components,
 
1206
                                                struct ldb_dn_component,
 
1207
                                                dn->comp_num + base->comp_num);
 
1208
                if ( ! dn->components) {
 
1209
                        dn->invalid = true;
 
1210
                        return false;
 
1211
                }
 
1212
 
 
1213
                for (i = 0; i < base->comp_num; dn->comp_num++, i++) {
 
1214
                        dn->components[dn->comp_num] = ldb_dn_copy_component(dn->components, &base->components[i]);
 
1215
                        if (dn->components[dn->comp_num].value.data == NULL) {
 
1216
                                dn->invalid = true;
 
1217
                                return false;
 
1218
                        }
 
1219
                }
 
1220
 
 
1221
                if (dn->casefold && s) {
 
1222
                        if (*dn->casefold) {
 
1223
                                t = talloc_asprintf(dn, "%s,%s", dn->casefold, s);
 
1224
                        } else {
 
1225
                                t = talloc_strdup(dn, s);
 
1226
                        }
 
1227
                        LDB_FREE(dn->casefold);
 
1228
                        dn->casefold = t;
 
1229
                }
 
1230
        }
 
1231
 
 
1232
        if (dn->linearized) {
 
1233
 
 
1234
                s = ldb_dn_get_linearized(base);
 
1235
                if ( ! s) {
 
1236
                        return false;
 
1237
                }
 
1238
                
 
1239
                if (*dn->linearized) {
 
1240
                        t = talloc_asprintf(dn, "%s,%s", dn->linearized, s);
 
1241
                } else {
 
1242
                        t = talloc_strdup(dn, s);
 
1243
                }
 
1244
                if ( ! t) {
 
1245
                        dn->invalid = true;
 
1246
                        return false;
 
1247
                }
 
1248
                LDB_FREE(dn->linearized);
 
1249
                dn->linearized = t;
 
1250
        }
 
1251
 
 
1252
        /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
 
1253
        if (dn->extended_linearized) {
 
1254
                LDB_FREE(dn->extended_linearized);
 
1255
        }
 
1256
 
 
1257
        LDB_FREE(dn->extended_components);
 
1258
        dn->extended_comp_num = 0;
 
1259
        return true;
 
1260
}
 
1261
 
 
1262
/* modify the given dn by adding a base.
 
1263
 *
 
1264
 * return true if successful and false if not
 
1265
 * if false is returned the dn may be marked invalid
 
1266
 */
 
1267
bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...)
 
1268
{
 
1269
        struct ldb_dn *base;
 
1270
        char *base_str;
 
1271
        va_list ap;
 
1272
        bool ret;
 
1273
 
 
1274
        if ( !dn || dn->invalid) {
 
1275
                return false;
 
1276
        }
 
1277
 
 
1278
        va_start(ap, base_fmt);
 
1279
        base_str = talloc_vasprintf(dn, base_fmt, ap);
 
1280
        va_end(ap);
 
1281
 
 
1282
        if (base_str == NULL) {
 
1283
                return false;
 
1284
        }
 
1285
 
 
1286
        base = ldb_dn_new(base_str, dn->ldb, base_str);
 
1287
 
 
1288
        ret = ldb_dn_add_base(dn, base);
 
1289
 
 
1290
        talloc_free(base_str);
 
1291
 
 
1292
        return ret;
 
1293
}       
 
1294
 
 
1295
/* modify the given dn by adding children elements.
 
1296
 *
 
1297
 * return true if successful and false if not
 
1298
 * if false is returned the dn may be marked invalid
 
1299
 */
 
1300
bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
 
1301
{
 
1302
        const char *s;
 
1303
        char *t;
 
1304
 
 
1305
        if ( !child || child->invalid || !dn || dn->invalid) {
 
1306
                return false;
 
1307
        }
 
1308
 
 
1309
        if (dn->components) {
 
1310
                int n, i, j;
 
1311
 
 
1312
                if ( ! ldb_dn_validate(child)) {
 
1313
                        return false;
 
1314
                }
 
1315
 
 
1316
                s = NULL;
 
1317
                if (dn->valid_case) {
 
1318
                        if ( ! (s = ldb_dn_get_casefold(child))) {
 
1319
                                return false;
 
1320
                        }
 
1321
                }
 
1322
 
 
1323
                n = dn->comp_num + child->comp_num;
 
1324
 
 
1325
                dn->components = talloc_realloc(dn,
 
1326
                                                dn->components,
 
1327
                                                struct ldb_dn_component,
 
1328
                                                n);
 
1329
                if ( ! dn->components) {
 
1330
                        dn->invalid = true;
 
1331
                        return false;
 
1332
                }
 
1333
 
 
1334
                for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) {
 
1335
                        dn->components[j] = dn->components[i];
 
1336
                }
 
1337
 
 
1338
                for (i = 0; i < child->comp_num; i++) { 
 
1339
                        dn->components[i] = ldb_dn_copy_component(dn->components, &child->components[i]);
 
1340
                        if (dn->components[i].value.data == NULL) {
 
1341
                                dn->invalid = true;
 
1342
                                return false;
 
1343
                        }
 
1344
                }
 
1345
 
 
1346
                dn->comp_num = n;
 
1347
 
 
1348
                if (dn->casefold && s) {
 
1349
                        t = talloc_asprintf(dn, "%s,%s", s, dn->casefold);
 
1350
                        LDB_FREE(dn->casefold);
 
1351
                        dn->casefold = t;
 
1352
                }
 
1353
        }
 
1354
 
 
1355
        if (dn->linearized) {
 
1356
 
 
1357
                s = ldb_dn_get_linearized(child);
 
1358
                if ( ! s) {
 
1359
                        return false;
 
1360
                }
 
1361
                
 
1362
                t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
 
1363
                if ( ! t) {
 
1364
                        dn->invalid = true;
 
1365
                        return false;
 
1366
                }
 
1367
                LDB_FREE(dn->linearized);
 
1368
                dn->linearized = t;
 
1369
        }
 
1370
 
 
1371
        /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
 
1372
        LDB_FREE(dn->extended_linearized);
 
1373
 
 
1374
        LDB_FREE(dn->extended_components);
 
1375
        dn->extended_comp_num = 0;
 
1376
 
 
1377
        return true;
 
1378
}
 
1379
 
 
1380
/* modify the given dn by adding children elements.
 
1381
 *
 
1382
 * return true if successful and false if not
 
1383
 * if false is returned the dn may be marked invalid
 
1384
 */
 
1385
bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
 
1386
{
 
1387
        struct ldb_dn *child;
 
1388
        char *child_str;
 
1389
        va_list ap;
 
1390
        bool ret;
 
1391
 
 
1392
        if ( !dn || dn->invalid) {
 
1393
                return false;
 
1394
        }
 
1395
 
 
1396
        va_start(ap, child_fmt);
 
1397
        child_str = talloc_vasprintf(dn, child_fmt, ap);
 
1398
        va_end(ap);
 
1399
 
 
1400
        if (child_str == NULL) {
 
1401
                return false;
 
1402
        }
 
1403
 
 
1404
        child = ldb_dn_new(child_str, dn->ldb, child_str);
 
1405
 
 
1406
        ret = ldb_dn_add_child(dn, child);
 
1407
 
 
1408
        talloc_free(child_str);
 
1409
 
 
1410
        return ret;
 
1411
}
 
1412
 
 
1413
bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
 
1414
{
 
1415
        int i;
 
1416
 
 
1417
        if ( ! ldb_dn_validate(dn)) {
 
1418
                return false;
 
1419
        }
 
1420
 
 
1421
        if (dn->comp_num < num) {
 
1422
                return false;
 
1423
        }
 
1424
 
 
1425
        /* free components */
 
1426
        for (i = num; i > 0; i--) {
 
1427
                LDB_FREE(dn->components[dn->comp_num - i].name);
 
1428
                LDB_FREE(dn->components[dn->comp_num - i].value.data);
 
1429
                LDB_FREE(dn->components[dn->comp_num - i].cf_name);
 
1430
                LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
 
1431
        }
 
1432
        
 
1433
        dn->comp_num -= num;
 
1434
 
 
1435
        if (dn->valid_case) {
 
1436
                for (i = 0; i < dn->comp_num; i++) {
 
1437
                        LDB_FREE(dn->components[i].cf_name);
 
1438
                        LDB_FREE(dn->components[i].cf_value.data);
 
1439
                }
 
1440
                dn->valid_case = false;
 
1441
        }
 
1442
 
 
1443
        LDB_FREE(dn->casefold);
 
1444
        LDB_FREE(dn->linearized);
 
1445
 
 
1446
        /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
 
1447
        LDB_FREE(dn->extended_linearized);
 
1448
 
 
1449
        LDB_FREE(dn->extended_components);
 
1450
        dn->extended_comp_num = 0;
 
1451
 
 
1452
        return true;
 
1453
}
 
1454
 
 
1455
bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
 
1456
{
 
1457
        int i, j;
 
1458
 
 
1459
        if ( ! ldb_dn_validate(dn)) {
 
1460
                return false;
 
1461
        }
 
1462
 
 
1463
        if (dn->comp_num < num) {
 
1464
                return false;
 
1465
        }
 
1466
 
 
1467
        for (i = 0, j = num; j < dn->comp_num; i++, j++) {
 
1468
                if (i < num) {
 
1469
                        LDB_FREE(dn->components[i].name);
 
1470
                        LDB_FREE(dn->components[i].value.data);
 
1471
                        LDB_FREE(dn->components[i].cf_name);
 
1472
                        LDB_FREE(dn->components[i].cf_value.data);
 
1473
                }
 
1474
                dn->components[i] = dn->components[j];
 
1475
        }
 
1476
 
 
1477
        dn->comp_num -= num;
 
1478
 
 
1479
        if (dn->valid_case) {
 
1480
                for (i = 0; i < dn->comp_num; i++) {
 
1481
                        LDB_FREE(dn->components[i].cf_name);
 
1482
                        LDB_FREE(dn->components[i].cf_value.data);
 
1483
                }
 
1484
                dn->valid_case = false;
 
1485
        }
 
1486
 
 
1487
        LDB_FREE(dn->casefold);
 
1488
        LDB_FREE(dn->linearized);
 
1489
 
 
1490
        /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
 
1491
        LDB_FREE(dn->extended_linearized);
 
1492
 
 
1493
        LDB_FREE(dn->extended_components);
 
1494
        dn->extended_comp_num = 0;
 
1495
        return true;
 
1496
}
 
1497
 
 
1498
struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
 
1499
{
 
1500
        struct ldb_dn *new_dn;
 
1501
 
 
1502
        new_dn = ldb_dn_copy(mem_ctx, dn);
 
1503
        if ( !new_dn ) {
 
1504
                return NULL;
 
1505
        }
 
1506
 
 
1507
        if ( ! ldb_dn_remove_child_components(new_dn, 1)) {
 
1508
                talloc_free(new_dn);
 
1509
                return NULL;
 
1510
        }
 
1511
 
 
1512
        /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
 
1513
        LDB_FREE(dn->extended_linearized);
 
1514
 
 
1515
        LDB_FREE(dn->extended_components);
 
1516
        dn->extended_comp_num = 0;
 
1517
        return new_dn;
 
1518
}
 
1519
 
 
1520
/* Create a 'canonical name' string from a DN:
 
1521
 
 
1522
   ie dc=samba,dc=org -> samba.org/
 
1523
      uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
 
1524
 
 
1525
   There are two formats, the EX format has the last / replaced with a newline (\n).
 
1526
 
 
1527
*/
 
1528
static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
 
1529
        int i;
 
1530
        TALLOC_CTX *tmpctx;
 
1531
        char *cracked = NULL;
 
1532
        const char *format = (ex_format ? "\n" : "/" );
 
1533
 
 
1534
        if ( ! ldb_dn_validate(dn)) {
 
1535
                return NULL;
 
1536
        }
 
1537
 
 
1538
        tmpctx = talloc_new(mem_ctx);
 
1539
 
 
1540
        /* Walk backwards down the DN, grabbing 'dc' components at first */
 
1541
        for (i = dn->comp_num - 1 ; i >= 0; i--) {
 
1542
                if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
 
1543
                        break;
 
1544
                }
 
1545
                if (cracked) {
 
1546
                        cracked = talloc_asprintf(tmpctx, "%s.%s",
 
1547
                                                  ldb_dn_escape_value(tmpctx, dn->components[i].value),
 
1548
                                                  cracked);
 
1549
                } else {
 
1550
                        cracked = ldb_dn_escape_value(tmpctx, dn->components[i].value);
 
1551
                }
 
1552
                if (!cracked) {
 
1553
                        goto done;
 
1554
                }
 
1555
        }
 
1556
 
 
1557
        /* Only domain components?  Finish here */
 
1558
        if (i < 0) {
 
1559
                cracked = talloc_strdup_append_buffer(cracked, format);
 
1560
                talloc_steal(mem_ctx, cracked);
 
1561
                goto done;
 
1562
        }
 
1563
 
 
1564
        /* Now walk backwards appending remaining components */
 
1565
        for (; i > 0; i--) {
 
1566
                cracked = talloc_asprintf_append_buffer(cracked, "/%s", 
 
1567
                                                        ldb_dn_escape_value(tmpctx, dn->components[i].value));
 
1568
                if (!cracked) {
 
1569
                        goto done;
 
1570
                }
 
1571
        }
 
1572
 
 
1573
        /* Last one, possibly a newline for the 'ex' format */
 
1574
        cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format,
 
1575
                                                ldb_dn_escape_value(tmpctx, dn->components[i].value));
 
1576
 
 
1577
        talloc_steal(mem_ctx, cracked);
 
1578
done:
 
1579
        talloc_free(tmpctx);
 
1580
        return cracked;
 
1581
}
 
1582
 
 
1583
/* Wrapper functions for the above, for the two different string formats */
 
1584
char *ldb_dn_canonical_string(void *mem_ctx, struct ldb_dn *dn) {
 
1585
        return ldb_dn_canonical(mem_ctx, dn, 0);
 
1586
 
 
1587
}
 
1588
 
 
1589
char *ldb_dn_canonical_ex_string(void *mem_ctx, struct ldb_dn *dn) {
 
1590
        return ldb_dn_canonical(mem_ctx, dn, 1);
 
1591
}
 
1592
 
 
1593
int ldb_dn_get_comp_num(struct ldb_dn *dn)
 
1594
{
 
1595
        if ( ! ldb_dn_validate(dn)) {
 
1596
                return -1;
 
1597
        }
 
1598
        return dn->comp_num;
 
1599
}
 
1600
 
 
1601
const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num)
 
1602
{
 
1603
        if ( ! ldb_dn_validate(dn)) {
 
1604
                return NULL;
 
1605
        }
 
1606
        if (num >= dn->comp_num) return NULL;
 
1607
        return dn->components[num].name;
 
1608
}
 
1609
 
 
1610
const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num)
 
1611
{
 
1612
        if ( ! ldb_dn_validate(dn)) {
 
1613
                return NULL;
 
1614
        }
 
1615
        if (num >= dn->comp_num) return NULL;
 
1616
        return &dn->components[num].value;
 
1617
}
 
1618
 
 
1619
const char *ldb_dn_get_rdn_name(struct ldb_dn *dn)
 
1620
{
 
1621
        if ( ! ldb_dn_validate(dn)) {
 
1622
                return NULL;
 
1623
        }
 
1624
        if (dn->comp_num == 0) return NULL;
 
1625
        return dn->components[0].name;
 
1626
}
 
1627
 
 
1628
const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn)
 
1629
{
 
1630
        if ( ! ldb_dn_validate(dn)) {
 
1631
                return NULL;
 
1632
        }
 
1633
        if (dn->comp_num == 0) return NULL;
 
1634
        return &dn->components[0].value;
 
1635
}
 
1636
 
 
1637
int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
 
1638
{
 
1639
        char *n;
 
1640
        struct ldb_val v;
 
1641
 
 
1642
        if ( ! ldb_dn_validate(dn)) {
 
1643
                return LDB_ERR_OTHER;
 
1644
        }
 
1645
 
 
1646
        if (num >= dn->comp_num) {
 
1647
                return LDB_ERR_OTHER;
 
1648
        }
 
1649
 
 
1650
        n = talloc_strdup(dn, name);
 
1651
        if ( ! n) {
 
1652
                return LDB_ERR_OTHER;
 
1653
        }
 
1654
 
 
1655
        v.length = val.length;
 
1656
        v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
 
1657
        if ( ! v.data) {
 
1658
                talloc_free(n);
 
1659
                return LDB_ERR_OTHER;
 
1660
        }
 
1661
 
 
1662
        talloc_free(dn->components[num].name);
 
1663
        talloc_free(dn->components[num].value.data);
 
1664
        dn->components[num].name = n;
 
1665
        dn->components[num].value = v;
 
1666
 
 
1667
        if (dn->valid_case) {
 
1668
                int i;
 
1669
                for (i = 0; i < dn->comp_num; i++) {
 
1670
                        LDB_FREE(dn->components[i].cf_name);
 
1671
                        LDB_FREE(dn->components[i].cf_value.data);
 
1672
                }
 
1673
                dn->valid_case = false;
 
1674
        }
 
1675
        LDB_FREE(dn->casefold);
 
1676
        LDB_FREE(dn->linearized);
 
1677
 
 
1678
        /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
 
1679
        LDB_FREE(dn->extended_linearized);
 
1680
 
 
1681
        dn->extended_comp_num = 0;
 
1682
        LDB_FREE(dn->extended_components);
 
1683
        return LDB_SUCCESS;
 
1684
}
 
1685
 
 
1686
const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name)
 
1687
{
 
1688
        int i;
 
1689
        if ( ! ldb_dn_validate(dn)) {
 
1690
                return NULL;
 
1691
        }
 
1692
        for (i=0; i < dn->extended_comp_num; i++) {
 
1693
                if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
 
1694
                        return &dn->extended_components[i].value;
 
1695
                }
 
1696
        }
 
1697
        return NULL;
 
1698
}
 
1699
 
 
1700
int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val)
 
1701
{
 
1702
        struct ldb_dn_extended_component *p;
 
1703
        int i;
 
1704
                                
 
1705
        if ( ! ldb_dn_validate(dn)) {
 
1706
                return LDB_ERR_OTHER;
 
1707
        }
 
1708
 
 
1709
        for (i=0; i < dn->extended_comp_num; i++) {
 
1710
                if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
 
1711
                        if (val) {
 
1712
                                dn->extended_components[i].value = ldb_val_dup(dn->extended_components, val);
 
1713
 
 
1714
                                dn->extended_components[i].name = talloc_strdup(dn->extended_components, name);
 
1715
                                if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
 
1716
                                        dn->invalid = true;
 
1717
                                        return LDB_ERR_OPERATIONS_ERROR;
 
1718
                                }
 
1719
        
 
1720
                        } else {
 
1721
                                if (i != (dn->extended_comp_num - 1)) {
 
1722
                                        memmove(&dn->extended_components[i], &dn->extended_components[i+1],
 
1723
                                                ((dn->extended_comp_num-1) - i)*sizeof(*dn->extended_components));
 
1724
                                }
 
1725
                                dn->extended_comp_num--;
 
1726
                                
 
1727
                                dn->extended_components = talloc_realloc(dn,
 
1728
                                                   dn->extended_components,
 
1729
                                                   struct ldb_dn_extended_component,
 
1730
                                                   dn->extended_comp_num);
 
1731
                                if (!dn->extended_components) {
 
1732
                                        dn->invalid = true;
 
1733
                                        return LDB_ERR_OPERATIONS_ERROR;
 
1734
                                }
 
1735
                                return LDB_SUCCESS;
 
1736
                        }
 
1737
                }
 
1738
        }
 
1739
 
 
1740
        p = dn->extended_components
 
1741
                = talloc_realloc(dn,
 
1742
                                 dn->extended_components,
 
1743
                                 struct ldb_dn_extended_component,
 
1744
                                 dn->extended_comp_num + 1);
 
1745
        if (!dn->extended_components) {
 
1746
                dn->invalid = true;
 
1747
                return LDB_ERR_OPERATIONS_ERROR;
 
1748
        }
 
1749
        
 
1750
        p[dn->extended_comp_num].value = ldb_val_dup(dn->extended_components, val);
 
1751
        p[dn->extended_comp_num].name = talloc_strdup(p, name);
 
1752
        
 
1753
        if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
 
1754
                dn->invalid = true;
 
1755
                return LDB_ERR_OPERATIONS_ERROR;
 
1756
        }
 
1757
        dn->extended_components = p;
 
1758
        dn->extended_comp_num++;
 
1759
        
 
1760
        return LDB_SUCCESS;
 
1761
}
 
1762
 
 
1763
void ldb_dn_remove_extended_components(struct ldb_dn *dn)
 
1764
{
 
1765
        dn->extended_comp_num = 0;
 
1766
        LDB_FREE(dn->extended_components);      
 
1767
}
 
1768
 
 
1769
bool ldb_dn_is_valid(struct ldb_dn *dn)
 
1770
{
 
1771
        if ( ! dn) return false;
 
1772
        return ! dn->invalid;
 
1773
}
 
1774
 
 
1775
bool ldb_dn_is_special(struct ldb_dn *dn)
 
1776
{
 
1777
        if ( ! dn || dn->invalid) return false;
 
1778
        return dn->special;
 
1779
}
 
1780
 
 
1781
bool ldb_dn_has_extended(struct ldb_dn *dn)
 
1782
{
 
1783
        if ( ! dn || dn->invalid) return false;
 
1784
        if (dn->extended_linearized && (dn->extended_linearized[0] == '<')) return true;
 
1785
        return dn->extended_comp_num != 0;
 
1786
}
 
1787
 
 
1788
bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
 
1789
{
 
1790
        if ( ! dn || dn->invalid) return false;
 
1791
        return ! strcmp(dn->linearized, check);
 
1792
}
 
1793
 
 
1794
bool ldb_dn_is_null(struct ldb_dn *dn)
 
1795
{
 
1796
        if ( ! dn || dn->invalid) return false;
 
1797
        if (ldb_dn_has_extended(dn)) return false;
 
1798
        if (dn->linearized && (dn->linearized[0] == '\0')) return true;
 
1799
        return false;
 
1800
}