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