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