1 /*
2    ldb database library - ldif handlers for Samba
3 
4    Copyright (C) Andrew Tridgell 2005
5    Copyright (C) Andrew Bartlett 2006
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 2 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, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24 
25 #include "includes.h"
26 #include "ldb/include/includes.h"
27 #include "ldb/include/ldb_handlers.h"
28 
29 #include "librpc/gen_ndr/ndr_security.h"
30 #include "librpc/gen_ndr/ndr_misc.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "libcli/security/security.h"
33 
34 /*
35   convert a ldif formatted objectSid to a NDR formatted blob
36 */
ldif_read_objectSid(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)37 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
38 			       const struct ldb_val *in, struct ldb_val *out)
39 {
40 	struct dom_sid *sid;
41 	NTSTATUS status;
42 	sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data);
43 	if (sid == NULL) {
44 		return -1;
45 	}
46 	status = ndr_push_struct_blob(out, mem_ctx, sid,
47 				      (ndr_push_flags_fn_t)ndr_push_dom_sid);
48 	talloc_free(sid);
49 	if (!NT_STATUS_IS_OK(status)) {
50 		return -1;
51 	}
52 	return 0;
53 }
54 
55 /*
56   convert a NDR formatted blob to a ldif formatted objectSid
57 */
ldif_write_objectSid(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)58 static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
59 				const struct ldb_val *in, struct ldb_val *out)
60 {
61 	struct dom_sid *sid;
62 	NTSTATUS status;
63 	sid = talloc(mem_ctx, struct dom_sid);
64 	if (sid == NULL) {
65 		return -1;
66 	}
67 	status = ndr_pull_struct_blob(in, sid, sid,
68 				      (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
69 	if (!NT_STATUS_IS_OK(status)) {
70 		talloc_free(sid);
71 		return -1;
72 	}
73 	out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
74 	talloc_free(sid);
75 	if (out->data == NULL) {
76 		return -1;
77 	}
78 	out->length = strlen((const char *)out->data);
79 	return 0;
80 }
81 
ldb_comparision_objectSid_isString(const struct ldb_val * v)82 static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v)
83 {
84 	if (v->length < 3) {
85 		return False;
86 	}
87 
88 	if (strncmp("S-", (const char *)v->data, 2) != 0) return False;
89 
90 	return True;
91 }
92 
93 /*
94   compare two objectSids
95 */
ldb_comparison_objectSid(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * v1,const struct ldb_val * v2)96 static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
97 				    const struct ldb_val *v1, const struct ldb_val *v2)
98 {
99 	if (ldb_comparision_objectSid_isString(v1) && ldb_comparision_objectSid_isString(v2)) {
100 		return strcmp((const char *)v1->data, (const char *)v2->data);
101 	} else if (ldb_comparision_objectSid_isString(v1)
102 		   && !ldb_comparision_objectSid_isString(v2)) {
103 		struct ldb_val v;
104 		int ret;
105 		if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
106 			return -1;
107 		}
108 		ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
109 		talloc_free(v.data);
110 		return ret;
111 	} else if (!ldb_comparision_objectSid_isString(v1)
112 		   && ldb_comparision_objectSid_isString(v2)) {
113 		struct ldb_val v;
114 		int ret;
115 		if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
116 			return -1;
117 		}
118 		ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
119 		talloc_free(v.data);
120 		return ret;
121 	}
122 	return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
123 }
124 
125 /*
126   canonicalise a objectSid
127 */
ldb_canonicalise_objectSid(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)128 static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
129 				      const struct ldb_val *in, struct ldb_val *out)
130 {
131 	if (ldb_comparision_objectSid_isString(in)) {
132 		return ldif_read_objectSid(ldb, mem_ctx, in, out);
133 	}
134 	return ldb_handler_copy(ldb, mem_ctx, in, out);
135 }
136 
137 /*
138   convert a ldif formatted objectGUID to a NDR formatted blob
139 */
ldif_read_objectGUID(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)140 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
141 			        const struct ldb_val *in, struct ldb_val *out)
142 {
143 	struct GUID guid;
144 	NTSTATUS status;
145 
146 	status = GUID_from_string((const char *)in->data, &guid);
147 	if (!NT_STATUS_IS_OK(status)) {
148 		return -1;
149 	}
150 
151 	status = ndr_push_struct_blob(out, mem_ctx, &guid,
152 				      (ndr_push_flags_fn_t)ndr_push_GUID);
153 	if (!NT_STATUS_IS_OK(status)) {
154 		return -1;
155 	}
156 	return 0;
157 }
158 
159 /*
160   convert a NDR formatted blob to a ldif formatted objectGUID
161 */
ldif_write_objectGUID(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)162 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
163 				 const struct ldb_val *in, struct ldb_val *out)
164 {
165 	struct GUID guid;
166 	NTSTATUS status;
167 	status = ndr_pull_struct_blob(in, mem_ctx, &guid,
168 				      (ndr_pull_flags_fn_t)ndr_pull_GUID);
169 	if (!NT_STATUS_IS_OK(status)) {
170 		return -1;
171 	}
172 	out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
173 	if (out->data == NULL) {
174 		return -1;
175 	}
176 	out->length = strlen((const char *)out->data);
177 	return 0;
178 }
179 
ldb_comparision_objectGUID_isString(const struct ldb_val * v)180 static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v)
181 {
182 	struct GUID guid;
183 	NTSTATUS status;
184 
185 	if (v->length < 33) return False;
186 
187 	/* see if the input if null-terninated (safety check for the below) */
188 	if (v->data[v->length] != '\0') return False;
189 
190 	status = GUID_from_string((const char *)v->data, &guid);
191 	if (!NT_STATUS_IS_OK(status)) {
192 		return False;
193 	}
194 
195 	return True;
196 }
197 
198 /*
199   compare two objectGUIDs
200 */
ldb_comparison_objectGUID(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * v1,const struct ldb_val * v2)201 static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
202 				     const struct ldb_val *v1, const struct ldb_val *v2)
203 {
204 	if (ldb_comparision_objectGUID_isString(v1) && ldb_comparision_objectGUID_isString(v2)) {
205 		return strcmp((const char *)v1->data, (const char *)v2->data);
206 	} else if (ldb_comparision_objectGUID_isString(v1)
207 		   && !ldb_comparision_objectGUID_isString(v2)) {
208 		struct ldb_val v;
209 		int ret;
210 		if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
211 			return -1;
212 		}
213 		ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
214 		talloc_free(v.data);
215 		return ret;
216 	} else if (!ldb_comparision_objectGUID_isString(v1)
217 		   && ldb_comparision_objectGUID_isString(v2)) {
218 		struct ldb_val v;
219 		int ret;
220 		if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
221 			return -1;
222 		}
223 		ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
224 		talloc_free(v.data);
225 		return ret;
226 	}
227 	return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
228 }
229 
230 /*
231   canonicalise a objectGUID
232 */
ldb_canonicalise_objectGUID(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)233 static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
234 				       const struct ldb_val *in, struct ldb_val *out)
235 {
236 	if (ldb_comparision_objectGUID_isString(in)) {
237 		return ldif_read_objectGUID(ldb, mem_ctx, in, out);
238 	}
239 	return ldb_handler_copy(ldb, mem_ctx, in, out);
240 }
241 
242 
243 /*
244   convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
245 */
ldif_read_ntSecurityDescriptor(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)246 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
247 					  const struct ldb_val *in, struct ldb_val *out)
248 {
249 	struct security_descriptor *sd;
250 	NTSTATUS status;
251 
252 	sd = sddl_decode(mem_ctx, (const char *)in->data, NULL);
253 	if (sd == NULL) {
254 		return -1;
255 	}
256 	status = ndr_push_struct_blob(out, mem_ctx, sd,
257 				      (ndr_push_flags_fn_t)ndr_push_security_descriptor);
258 	talloc_free(sd);
259 	if (!NT_STATUS_IS_OK(status)) {
260 		return -1;
261 	}
262 	return 0;
263 }
264 
265 /*
266   convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
267 */
ldif_write_ntSecurityDescriptor(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)268 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
269 					   const struct ldb_val *in, struct ldb_val *out)
270 {
271 	struct security_descriptor *sd;
272 	NTSTATUS status;
273 
274 	sd = talloc(mem_ctx, struct security_descriptor);
275 	if (sd == NULL) {
276 		return -1;
277 	}
278 	status = ndr_pull_struct_blob(in, sd, sd,
279 				      (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
280 	if (!NT_STATUS_IS_OK(status)) {
281 		talloc_free(sd);
282 		return -1;
283 	}
284 	out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);
285 	talloc_free(sd);
286 	if (out->data == NULL) {
287 		return -1;
288 	}
289 	out->length = strlen((const char *)out->data);
290 	return 0;
291 }
292 
293 /*
294    canonicolise an objectCategory.  We use the short form as the cannoical form:
295    cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
296 */
297 
ldif_canonicalise_objectCategory(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * in,struct ldb_val * out)298 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
299 					    const struct ldb_val *in, struct ldb_val *out)
300 {
301 	struct ldb_dn *dn1 = NULL;
302 	char *oc1, *oc2;
303 
304 	dn1 = ldb_dn_new(mem_ctx, ldb, (char *)in->data);
305 	if ( ! ldb_dn_validate(dn1)) {
306 		oc1 = talloc_strndup(mem_ctx, (char *)in->data, in->length);
307 	} else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
308 		const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
309 		oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
310 	} else {
311 		return -1;
312 	}
313 
314 	oc2 = ldb_casefold(ldb, mem_ctx, oc1);
315 	out->data = (void *)oc2;
316 	out->length = strlen(oc2);
317 	talloc_free(oc1);
318 	talloc_free(dn1);
319 	return 0;
320 }
321 
ldif_comparison_objectCategory(struct ldb_context * ldb,void * mem_ctx,const struct ldb_val * v1,const struct ldb_val * v2)322 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
323 					  const struct ldb_val *v1,
324 					  const struct ldb_val *v2)
325 {
326 	struct ldb_dn *dn1 = NULL, *dn2 = NULL;
327 	const char *oc1, *oc2;
328 
329 	dn1 = ldb_dn_new(mem_ctx, ldb, (char *)v1->data);
330 	if ( ! ldb_dn_validate(dn1)) {
331 		oc1 = talloc_strndup(mem_ctx, (char *)v1->data, v1->length);
332 	} else if (ldb_dn_get_comp_num(dn1) >= 1 && strcasecmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
333 		const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
334 		oc1 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
335 	} else {
336 		oc1 = NULL;
337 	}
338 
339 	dn2 = ldb_dn_new(mem_ctx, ldb, (char *)v2->data);
340 	if ( ! ldb_dn_validate(dn2)) {
341 		oc2 = talloc_strndup(mem_ctx, (char *)v2->data, v2->length);
342 	} else if (ldb_dn_get_comp_num(dn2) >= 2 && strcasecmp(ldb_dn_get_rdn_name(dn2), "cn") == 0) {
343 		const struct ldb_val *val = ldb_dn_get_rdn_val(dn2);
344 		oc2 = talloc_strndup(mem_ctx, (char *)val->data, val->length);
345 	} else {
346 		oc2 = NULL;
347 	}
348 
349 	oc1 = ldb_casefold(ldb, mem_ctx, oc1);
350 	oc2 = ldb_casefold(ldb, mem_ctx, oc2);
351 	if (!oc1 && oc2) {
352 		return -1;
353 	}
354 	if (oc1 && !oc2) {
355 		return 1;
356 	}
357 	if (!oc1 && !oc2) {
358 		return -1;
359 	}
360 
361 	return strcmp(oc1, oc2);
362 }
363 
364 static const struct ldb_attrib_handler samba_handlers[] = {
365 	{
366 		.attr            = "objectSid",
367 		.flags           = 0,
368 		.ldif_read_fn    = ldif_read_objectSid,
369 		.ldif_write_fn   = ldif_write_objectSid,
370 		.canonicalise_fn = ldb_canonicalise_objectSid,
371 		.comparison_fn   = ldb_comparison_objectSid
372 	},
373 	{
374 		.attr            = "securityIdentifier",
375 		.flags           = 0,
376 		.ldif_read_fn    = ldif_read_objectSid,
377 		.ldif_write_fn   = ldif_write_objectSid,
378 		.canonicalise_fn = ldb_canonicalise_objectSid,
379 		.comparison_fn   = ldb_comparison_objectSid
380 	},
381 	{
382 		.attr            = "ntSecurityDescriptor",
383 		.flags           = 0,
384 		.ldif_read_fn    = ldif_read_ntSecurityDescriptor,
385 		.ldif_write_fn   = ldif_write_ntSecurityDescriptor,
386 		.canonicalise_fn = ldb_handler_copy,
387 		.comparison_fn   = ldb_comparison_binary
388 	},
389 	{
390 		.attr            = "objectGUID",
391 		.flags           = 0,
392 		.ldif_read_fn    = ldif_read_objectGUID,
393 		.ldif_write_fn   = ldif_write_objectGUID,
394 		.canonicalise_fn = ldb_canonicalise_objectGUID,
395 		.comparison_fn   = ldb_comparison_objectGUID
396 	},
397 	{
398 		.attr            = "invocationId",
399 		.flags           = 0,
400 		.ldif_read_fn    = ldif_read_objectGUID,
401 		.ldif_write_fn   = ldif_write_objectGUID,
402 		.canonicalise_fn = ldb_canonicalise_objectGUID,
403 		.comparison_fn   = ldb_comparison_objectGUID
404 	},
405 	{
406 		.attr            = "schemaIDGUID",
407 		.flags           = 0,
408 		.ldif_read_fn    = ldif_read_objectGUID,
409 		.ldif_write_fn   = ldif_write_objectGUID,
410 		.canonicalise_fn = ldb_canonicalise_objectGUID,
411 		.comparison_fn   = ldb_comparison_objectGUID
412 	},
413 	{
414 		.attr            = "attributeSecurityGUID",
415 		.flags           = 0,
416 		.ldif_read_fn    = ldif_read_objectGUID,
417 		.ldif_write_fn   = ldif_write_objectGUID,
418 		.canonicalise_fn = ldb_canonicalise_objectGUID,
419 		.comparison_fn   = ldb_comparison_objectGUID
420 	},
421 	{
422 		.attr            = "parentGUID",
423 		.flags           = 0,
424 		.ldif_read_fn    = ldif_read_objectGUID,
425 		.ldif_write_fn   = ldif_write_objectGUID,
426 		.canonicalise_fn = ldb_canonicalise_objectGUID,
427 		.comparison_fn   = ldb_comparison_objectGUID
428 	},
429 	{
430 		.attr            = "siteGUID",
431 		.flags           = 0,
432 		.ldif_read_fn    = ldif_read_objectGUID,
433 		.ldif_write_fn   = ldif_write_objectGUID,
434 		.canonicalise_fn = ldb_canonicalise_objectGUID,
435 		.comparison_fn   = ldb_comparison_objectGUID
436 	},
437 	{
438 		.attr            = "pKTGUID",
439 		.flags           = 0,
440 		.ldif_read_fn    = ldif_read_objectGUID,
441 		.ldif_write_fn   = ldif_write_objectGUID,
442 		.canonicalise_fn = ldb_canonicalise_objectGUID,
443 		.comparison_fn   = ldb_comparison_objectGUID
444 	},
445 	{
446 		.attr            = "fRSVersionGUID",
447 		.flags           = 0,
448 		.ldif_read_fn    = ldif_read_objectGUID,
449 		.ldif_write_fn   = ldif_write_objectGUID,
450 		.canonicalise_fn = ldb_canonicalise_objectGUID,
451 		.comparison_fn   = ldb_comparison_objectGUID
452 	},
453 	{
454 		.attr            = "fRSReplicaSetGUID",
455 		.flags           = 0,
456 		.ldif_read_fn    = ldif_read_objectGUID,
457 		.ldif_write_fn   = ldif_write_objectGUID,
458 		.canonicalise_fn = ldb_canonicalise_objectGUID,
459 		.comparison_fn   = ldb_comparison_objectGUID
460 	},
461 	{
462 		.attr            = "netbootGUID",
463 		.flags           = 0,
464 		.ldif_read_fn    = ldif_read_objectGUID,
465 		.ldif_write_fn   = ldif_write_objectGUID,
466 		.canonicalise_fn = ldb_canonicalise_objectGUID,
467 		.comparison_fn   = ldb_comparison_objectGUID
468 	},
469 	{
470 		.attr            = "objectCategory",
471 		.flags           = 0,
472 		.ldif_read_fn    = ldb_handler_copy,
473 		.ldif_write_fn   = ldb_handler_copy,
474 		.canonicalise_fn = ldif_canonicalise_objectCategory,
475 		.comparison_fn   = ldif_comparison_objectCategory,
476 	},
477 	{
478 		.attr            = "member",
479 		.flags           = 0,
480 		.ldif_read_fn    = ldb_handler_copy,
481 		.ldif_write_fn   = ldb_handler_copy,
482 		.canonicalise_fn = ldb_canonicalise_dn,
483 		.comparison_fn   = ldb_comparison_dn,
484 	},
485 	{
486 		.attr            = "memberOf",
487 		.flags           = 0,
488 		.ldif_read_fn    = ldb_handler_copy,
489 		.ldif_write_fn   = ldb_handler_copy,
490 		.canonicalise_fn = ldb_canonicalise_dn,
491 		.comparison_fn   = ldb_comparison_dn,
492 	},
493 	{
494 		.attr            = "nCName",
495 		.flags           = 0,
496 		.ldif_read_fn    = ldb_handler_copy,
497 		.ldif_write_fn   = ldb_handler_copy,
498 		.canonicalise_fn = ldb_canonicalise_dn,
499 		.comparison_fn   = ldb_comparison_dn,
500 	},
501 	{
502 		.attr            = "schemaNamingContext",
503 		.flags           = 0,
504 		.ldif_read_fn    = ldb_handler_copy,
505 		.ldif_write_fn   = ldb_handler_copy,
506 		.canonicalise_fn = ldb_canonicalise_dn,
507 		.comparison_fn   = ldb_comparison_dn,
508 	},
509 	{
510 		.attr            = "configurationNamingContext",
511 		.flags           = 0,
512 		.ldif_read_fn    = ldb_handler_copy,
513 		.ldif_write_fn   = ldb_handler_copy,
514 		.canonicalise_fn = ldb_canonicalise_dn,
515 		.comparison_fn   = ldb_comparison_dn,
516 	},
517 	{
518 		.attr            = "rootDomainNamingContext",
519 		.flags           = 0,
520 		.ldif_read_fn    = ldb_handler_copy,
521 		.ldif_write_fn   = ldb_handler_copy,
522 		.canonicalise_fn = ldb_canonicalise_dn,
523 		.comparison_fn   = ldb_comparison_dn,
524 	},
525 	{
526 		.attr            = "defaultNamingContext",
527 		.flags           = 0,
528 		.ldif_read_fn    = ldb_handler_copy,
529 		.ldif_write_fn   = ldb_handler_copy,
530 		.canonicalise_fn = ldb_canonicalise_dn,
531 		.comparison_fn   = ldb_comparison_dn,
532 	},
533 	{
534 		.attr            = "subRefs",
535 		.flags           = 0,
536 		.ldif_read_fn    = ldb_handler_copy,
537 		.ldif_write_fn   = ldb_handler_copy,
538 		.canonicalise_fn = ldb_canonicalise_dn,
539 		.comparison_fn   = ldb_comparison_dn,
540 	},
541 	{
542 		.attr            = "dMDLocation",
543 		.flags           = 0,
544 		.ldif_read_fn    = ldb_handler_copy,
545 		.ldif_write_fn   = ldb_handler_copy,
546 		.canonicalise_fn = ldb_canonicalise_dn,
547 		.comparison_fn   = ldb_comparison_dn,
548 	},
549 	{
550 		.attr            = "serverReference",
551 		.flags           = 0,
552 		.ldif_read_fn    = ldb_handler_copy,
553 		.ldif_write_fn   = ldb_handler_copy,
554 		.canonicalise_fn = ldb_canonicalise_dn,
555 		.comparison_fn   = ldb_comparison_dn,
556 	},
557 	{
558 		.attr            = "masteredBy",
559 		.flags           = 0,
560 		.ldif_read_fn    = ldb_handler_copy,
561 		.ldif_write_fn   = ldb_handler_copy,
562 		.canonicalise_fn = ldb_canonicalise_dn,
563 		.comparison_fn   = ldb_comparison_dn,
564 	},
565 	{
566 		.attr            = "msDs-masteredBy",
567 		.flags           = 0,
568 		.ldif_read_fn    = ldb_handler_copy,
569 		.ldif_write_fn   = ldb_handler_copy,
570 		.canonicalise_fn = ldb_canonicalise_dn,
571 		.comparison_fn   = ldb_comparison_dn,
572 	},
573 	{
574 		.attr            = "subRefs",
575 		.flags           = 0,
576 		.ldif_read_fn    = ldb_handler_copy,
577 		.ldif_write_fn   = ldb_handler_copy,
578 		.canonicalise_fn = ldb_canonicalise_dn,
579 		.comparison_fn   = ldb_comparison_dn,
580 	},
581 	{
582 		.attr            = "fSMORoleOwner",
583 		.flags           = 0,
584 		.ldif_read_fn    = ldb_handler_copy,
585 		.ldif_write_fn   = ldb_handler_copy,
586 		.canonicalise_fn = ldb_canonicalise_dn,
587 		.comparison_fn   = ldb_comparison_dn,
588 	}
589 };
590 
591 /*
592   register the samba ldif handlers
593 */
ldb_register_samba_handlers(struct ldb_context * ldb)594 int ldb_register_samba_handlers(struct ldb_context *ldb)
595 {
596 	return ldb_set_attrib_handlers(ldb, samba_handlers, ARRAY_SIZE(samba_handlers));
597 }
598