1 | /*
|
---|
2 | ldb database library - ldif handlers for Samba
|
---|
3 |
|
---|
4 | Copyright (C) Andrew Tridgell 2005
|
---|
5 | Copyright (C) Andrew Bartlett 2006-2007
|
---|
6 | Copyright (C) Matthias Dieter Wallnöfer 2009
|
---|
7 | ** NOTE! The following LGPL license applies to the ldb
|
---|
8 | ** library. This does NOT imply that all of Samba is released
|
---|
9 | ** under the LGPL
|
---|
10 |
|
---|
11 | This library is free software; you can redistribute it and/or
|
---|
12 | modify it under the terms of the GNU Lesser General Public
|
---|
13 | License as published by the Free Software Foundation; either
|
---|
14 | version 3 of the License, or (at your option) any later version.
|
---|
15 |
|
---|
16 | This library is distributed in the hope that it will be useful,
|
---|
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
19 | Lesser General Public License for more details.
|
---|
20 |
|
---|
21 | You should have received a copy of the GNU Lesser General Public
|
---|
22 | License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
---|
23 | */
|
---|
24 |
|
---|
25 | #include "includes.h"
|
---|
26 | #include "lib/ldb/include/ldb.h"
|
---|
27 | #include "lib/ldb/include/ldb_module.h"
|
---|
28 | #include "ldb_handlers.h"
|
---|
29 | #include "dsdb/samdb/samdb.h"
|
---|
30 | #include "librpc/gen_ndr/ndr_security.h"
|
---|
31 | #include "librpc/gen_ndr/ndr_misc.h"
|
---|
32 | #include "librpc/gen_ndr/ndr_drsblobs.h"
|
---|
33 | #include "librpc/ndr/libndr.h"
|
---|
34 | #include "libcli/security/security.h"
|
---|
35 | #include "param/param.h"
|
---|
36 |
|
---|
37 | /*
|
---|
38 | use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
|
---|
39 | */
|
---|
40 | static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
|
---|
41 | const struct ldb_val *in, struct ldb_val *out,
|
---|
42 | size_t struct_size,
|
---|
43 | ndr_pull_flags_fn_t pull_fn,
|
---|
44 | ndr_print_fn_t print_fn)
|
---|
45 | {
|
---|
46 | uint8_t *p;
|
---|
47 | enum ndr_err_code err;
|
---|
48 | if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
|
---|
49 | return ldb_handler_copy(ldb, mem_ctx, in, out);
|
---|
50 | }
|
---|
51 | p = talloc_size(mem_ctx, struct_size);
|
---|
52 | err = ndr_pull_struct_blob(in, mem_ctx,
|
---|
53 | lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
|
---|
54 | p, pull_fn);
|
---|
55 | if (err != NDR_ERR_SUCCESS) {
|
---|
56 | talloc_free(p);
|
---|
57 | out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
|
---|
58 | out->length = strlen((const char *)out->data);
|
---|
59 | return 0;
|
---|
60 | }
|
---|
61 | out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
|
---|
62 | talloc_free(p);
|
---|
63 | if (out->data == NULL) {
|
---|
64 | return ldb_handler_copy(ldb, mem_ctx, in, out);
|
---|
65 | }
|
---|
66 | out->length = strlen((char *)out->data);
|
---|
67 | return 0;
|
---|
68 | }
|
---|
69 |
|
---|
70 | /*
|
---|
71 | convert a ldif formatted objectSid to a NDR formatted blob
|
---|
72 | */
|
---|
73 | static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
|
---|
74 | const struct ldb_val *in, struct ldb_val *out)
|
---|
75 | {
|
---|
76 | enum ndr_err_code ndr_err;
|
---|
77 | struct dom_sid *sid;
|
---|
78 | sid = dom_sid_parse_length(mem_ctx, in);
|
---|
79 | if (sid == NULL) {
|
---|
80 | return -1;
|
---|
81 | }
|
---|
82 | ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, sid,
|
---|
83 | (ndr_push_flags_fn_t)ndr_push_dom_sid);
|
---|
84 | talloc_free(sid);
|
---|
85 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
86 | return -1;
|
---|
87 | }
|
---|
88 | return 0;
|
---|
89 | }
|
---|
90 |
|
---|
91 | /*
|
---|
92 | convert a NDR formatted blob to a ldif formatted objectSid
|
---|
93 | */
|
---|
94 | static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
|
---|
95 | const struct ldb_val *in, struct ldb_val *out)
|
---|
96 | {
|
---|
97 | struct dom_sid *sid;
|
---|
98 | enum ndr_err_code ndr_err;
|
---|
99 |
|
---|
100 | sid = talloc(mem_ctx, struct dom_sid);
|
---|
101 | if (sid == NULL) {
|
---|
102 | return -1;
|
---|
103 | }
|
---|
104 | ndr_err = ndr_pull_struct_blob_all(in, sid, NULL, sid,
|
---|
105 | (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
|
---|
106 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
107 | talloc_free(sid);
|
---|
108 | return -1;
|
---|
109 | }
|
---|
110 | *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
|
---|
111 | talloc_free(sid);
|
---|
112 | if (out->data == NULL) {
|
---|
113 | return -1;
|
---|
114 | }
|
---|
115 | return 0;
|
---|
116 | }
|
---|
117 |
|
---|
118 | static bool ldif_comparision_objectSid_isString(const struct ldb_val *v)
|
---|
119 | {
|
---|
120 | if (v->length < 3) {
|
---|
121 | return false;
|
---|
122 | }
|
---|
123 |
|
---|
124 | if (strncmp("S-", (const char *)v->data, 2) != 0) return false;
|
---|
125 |
|
---|
126 | return true;
|
---|
127 | }
|
---|
128 |
|
---|
129 | /*
|
---|
130 | compare two objectSids
|
---|
131 | */
|
---|
132 | static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
|
---|
133 | const struct ldb_val *v1, const struct ldb_val *v2)
|
---|
134 | {
|
---|
135 | if (ldif_comparision_objectSid_isString(v1) && ldif_comparision_objectSid_isString(v2)) {
|
---|
136 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
137 | } else if (ldif_comparision_objectSid_isString(v1)
|
---|
138 | && !ldif_comparision_objectSid_isString(v2)) {
|
---|
139 | struct ldb_val v;
|
---|
140 | int ret;
|
---|
141 | if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
|
---|
142 | /* Perhaps not a string after all */
|
---|
143 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
144 | }
|
---|
145 | ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
|
---|
146 | talloc_free(v.data);
|
---|
147 | return ret;
|
---|
148 | } else if (!ldif_comparision_objectSid_isString(v1)
|
---|
149 | && ldif_comparision_objectSid_isString(v2)) {
|
---|
150 | struct ldb_val v;
|
---|
151 | int ret;
|
---|
152 | if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
|
---|
153 | /* Perhaps not a string after all */
|
---|
154 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
155 | }
|
---|
156 | ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
|
---|
157 | talloc_free(v.data);
|
---|
158 | return ret;
|
---|
159 | }
|
---|
160 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
161 | }
|
---|
162 |
|
---|
163 | /*
|
---|
164 | canonicalise a objectSid
|
---|
165 | */
|
---|
166 | static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
|
---|
167 | const struct ldb_val *in, struct ldb_val *out)
|
---|
168 | {
|
---|
169 | if (ldif_comparision_objectSid_isString(in)) {
|
---|
170 | if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
|
---|
171 | /* Perhaps not a string after all */
|
---|
172 | return ldb_handler_copy(ldb, mem_ctx, in, out);
|
---|
173 | }
|
---|
174 | return 0;
|
---|
175 | }
|
---|
176 | return ldb_handler_copy(ldb, mem_ctx, in, out);
|
---|
177 | }
|
---|
178 |
|
---|
179 | static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
|
---|
180 | const struct ldb_val *in, struct ldb_val *out)
|
---|
181 | {
|
---|
182 | struct dom_sid sid;
|
---|
183 | enum ndr_err_code ndr_err;
|
---|
184 | if (ldif_comparision_objectSid_isString(in)) {
|
---|
185 | if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
|
---|
186 | return 0;
|
---|
187 | }
|
---|
188 | }
|
---|
189 |
|
---|
190 | /* Perhaps not a string after all */
|
---|
191 | *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
|
---|
192 |
|
---|
193 | if (!out->data) {
|
---|
194 | return -1;
|
---|
195 | }
|
---|
196 |
|
---|
197 | (*out).length = strhex_to_str((char *)out->data, out->length,
|
---|
198 | (const char *)in->data, in->length);
|
---|
199 |
|
---|
200 | /* Check it looks like a SID */
|
---|
201 | ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL, &sid,
|
---|
202 | (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
|
---|
203 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
204 | return -1;
|
---|
205 | }
|
---|
206 | return 0;
|
---|
207 | }
|
---|
208 |
|
---|
209 | /*
|
---|
210 | convert a ldif formatted objectGUID to a NDR formatted blob
|
---|
211 | */
|
---|
212 | static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
|
---|
213 | const struct ldb_val *in, struct ldb_val *out)
|
---|
214 | {
|
---|
215 | struct GUID guid;
|
---|
216 | NTSTATUS status;
|
---|
217 | enum ndr_err_code ndr_err;
|
---|
218 |
|
---|
219 | status = GUID_from_data_blob(in, &guid);
|
---|
220 | if (!NT_STATUS_IS_OK(status)) {
|
---|
221 | return -1;
|
---|
222 | }
|
---|
223 |
|
---|
224 | ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, &guid,
|
---|
225 | (ndr_push_flags_fn_t)ndr_push_GUID);
|
---|
226 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
227 | return -1;
|
---|
228 | }
|
---|
229 | return 0;
|
---|
230 | }
|
---|
231 |
|
---|
232 | /*
|
---|
233 | convert a NDR formatted blob to a ldif formatted objectGUID
|
---|
234 | */
|
---|
235 | static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
|
---|
236 | const struct ldb_val *in, struct ldb_val *out)
|
---|
237 | {
|
---|
238 | struct GUID guid;
|
---|
239 | enum ndr_err_code ndr_err;
|
---|
240 | ndr_err = ndr_pull_struct_blob_all(in, mem_ctx, NULL, &guid,
|
---|
241 | (ndr_pull_flags_fn_t)ndr_pull_GUID);
|
---|
242 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
243 | return -1;
|
---|
244 | }
|
---|
245 | out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
|
---|
246 | if (out->data == NULL) {
|
---|
247 | return -1;
|
---|
248 | }
|
---|
249 | out->length = strlen((const char *)out->data);
|
---|
250 | return 0;
|
---|
251 | }
|
---|
252 |
|
---|
253 | static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
|
---|
254 | {
|
---|
255 | if (v->length != 36 && v->length != 38) return false;
|
---|
256 |
|
---|
257 | /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
|
---|
258 | return true;
|
---|
259 | }
|
---|
260 |
|
---|
261 | static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
|
---|
262 | const struct ldb_val *in, struct ldb_val *out)
|
---|
263 | {
|
---|
264 | struct GUID guid;
|
---|
265 | enum ndr_err_code ndr_err;
|
---|
266 | if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
|
---|
267 | return 0;
|
---|
268 | }
|
---|
269 |
|
---|
270 | /* Try as 'hex' form */
|
---|
271 | if (in->length != 32) {
|
---|
272 | return -1;
|
---|
273 | }
|
---|
274 |
|
---|
275 | *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
|
---|
276 |
|
---|
277 | if (!out->data) {
|
---|
278 | return -1;
|
---|
279 | }
|
---|
280 |
|
---|
281 | (*out).length = strhex_to_str((char *)out->data, out->length,
|
---|
282 | (const char *)in->data, in->length);
|
---|
283 |
|
---|
284 | /* Check it looks like a GUID */
|
---|
285 | ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, NULL, &guid,
|
---|
286 | (ndr_pull_flags_fn_t)ndr_pull_GUID);
|
---|
287 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
288 | return -1;
|
---|
289 | }
|
---|
290 | return 0;
|
---|
291 | }
|
---|
292 |
|
---|
293 | /*
|
---|
294 | compare two objectGUIDs
|
---|
295 | */
|
---|
296 | static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
|
---|
297 | const struct ldb_val *v1, const struct ldb_val *v2)
|
---|
298 | {
|
---|
299 | if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
|
---|
300 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
301 | } else if (ldif_comparision_objectGUID_isString(v1)
|
---|
302 | && !ldif_comparision_objectGUID_isString(v2)) {
|
---|
303 | struct ldb_val v;
|
---|
304 | int ret;
|
---|
305 | if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
|
---|
306 | /* Perhaps it wasn't a valid string after all */
|
---|
307 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
308 | }
|
---|
309 | ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
|
---|
310 | talloc_free(v.data);
|
---|
311 | return ret;
|
---|
312 | } else if (!ldif_comparision_objectGUID_isString(v1)
|
---|
313 | && ldif_comparision_objectGUID_isString(v2)) {
|
---|
314 | struct ldb_val v;
|
---|
315 | int ret;
|
---|
316 | if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
|
---|
317 | /* Perhaps it wasn't a valid string after all */
|
---|
318 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
319 | }
|
---|
320 | ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
|
---|
321 | talloc_free(v.data);
|
---|
322 | return ret;
|
---|
323 | }
|
---|
324 | return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
|
---|
325 | }
|
---|
326 |
|
---|
327 | /*
|
---|
328 | canonicalise a objectGUID
|
---|
329 | */
|
---|
330 | static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
|
---|
331 | const struct ldb_val *in, struct ldb_val *out)
|
---|
332 | {
|
---|
333 | if (ldif_comparision_objectGUID_isString(in)) {
|
---|
334 | if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
|
---|
335 | /* Perhaps it wasn't a valid string after all */
|
---|
336 | return ldb_handler_copy(ldb, mem_ctx, in, out);
|
---|
337 | }
|
---|
338 | return 0;
|
---|
339 | }
|
---|
340 | return ldb_handler_copy(ldb, mem_ctx, in, out);
|
---|
341 | }
|
---|
342 |
|
---|
343 |
|
---|
344 | /*
|
---|
345 | convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
|
---|
346 | */
|
---|
347 | static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
|
---|
348 | const struct ldb_val *in, struct ldb_val *out)
|
---|
349 | {
|
---|
350 | struct security_descriptor *sd;
|
---|
351 | enum ndr_err_code ndr_err;
|
---|
352 |
|
---|
353 | sd = talloc(mem_ctx, struct security_descriptor);
|
---|
354 | if (sd == NULL) {
|
---|
355 | return -1;
|
---|
356 | }
|
---|
357 |
|
---|
358 | ndr_err = ndr_pull_struct_blob(in, sd, NULL, sd,
|
---|
359 | (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
|
---|
360 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
361 | /* If this does not parse, then it is probably SDDL, and we should try it that way */
|
---|
362 |
|
---|
363 | const struct dom_sid *sid = samdb_domain_sid(ldb);
|
---|
364 | talloc_free(sd);
|
---|
365 | sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
|
---|
366 | if (sd == NULL) {
|
---|
367 | return -1;
|
---|
368 | }
|
---|
369 | }
|
---|
370 |
|
---|
371 | ndr_err = ndr_push_struct_blob(out, mem_ctx, NULL, sd,
|
---|
372 | (ndr_push_flags_fn_t)ndr_push_security_descriptor);
|
---|
373 | talloc_free(sd);
|
---|
374 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
375 | return -1;
|
---|
376 | }
|
---|
377 |
|
---|
378 | return 0;
|
---|
379 | }
|
---|
380 |
|
---|
381 | /*
|
---|
382 | convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
|
---|
383 | */
|
---|
384 | static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
|
---|
385 | const struct ldb_val *in, struct ldb_val *out)
|
---|
386 | {
|
---|
387 | struct security_descriptor *sd;
|
---|
388 | enum ndr_err_code ndr_err;
|
---|
389 |
|
---|
390 | if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
|
---|
391 | return ldif_write_NDR(ldb, mem_ctx, in, out,
|
---|
392 | sizeof(struct security_descriptor),
|
---|
393 | (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
|
---|
394 | (ndr_print_fn_t)ndr_print_security_descriptor);
|
---|
395 |
|
---|
396 | }
|
---|
397 |
|
---|
398 | sd = talloc(mem_ctx, struct security_descriptor);
|
---|
399 | if (sd == NULL) {
|
---|
400 | return -1;
|
---|
401 | }
|
---|
402 | /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
|
---|
403 | ndr_err = ndr_pull_struct_blob(in, sd, NULL, sd,
|
---|
404 | (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
|
---|
405 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
406 | talloc_free(sd);
|
---|
407 | return -1;
|
---|
408 | }
|
---|
409 | out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);
|
---|
410 | talloc_free(sd);
|
---|
411 | if (out->data == NULL) {
|
---|
412 | return -1;
|
---|
413 | }
|
---|
414 | out->length = strlen((const char *)out->data);
|
---|
415 | return 0;
|
---|
416 | }
|
---|
417 |
|
---|
418 | /*
|
---|
419 | canonicalise an objectCategory. We use the short form as the cannoical form:
|
---|
420 | cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
|
---|
421 | */
|
---|
422 |
|
---|
423 | static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
|
---|
424 | const struct ldb_val *in, struct ldb_val *out)
|
---|
425 | {
|
---|
426 | struct ldb_dn *dn1 = NULL;
|
---|
427 | const struct dsdb_schema *schema = dsdb_get_schema(ldb);
|
---|
428 | const struct dsdb_class *sclass;
|
---|
429 | TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
|
---|
430 | if (!tmp_ctx) {
|
---|
431 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
432 | }
|
---|
433 |
|
---|
434 | if (!schema) {
|
---|
435 | talloc_free(tmp_ctx);
|
---|
436 | *out = data_blob_talloc(mem_ctx, in->data, in->length);
|
---|
437 | if (in->data && !out->data) {
|
---|
438 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
439 | }
|
---|
440 | return LDB_SUCCESS;
|
---|
441 | }
|
---|
442 | dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
|
---|
443 | if ( ! ldb_dn_validate(dn1)) {
|
---|
444 | const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
|
---|
445 | sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
|
---|
446 | if (sclass) {
|
---|
447 | struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,
|
---|
448 | sclass->defaultObjectCategory);
|
---|
449 | *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
|
---|
450 | talloc_free(tmp_ctx);
|
---|
451 |
|
---|
452 | if (!out->data) {
|
---|
453 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
454 | }
|
---|
455 | return LDB_SUCCESS;
|
---|
456 | } else {
|
---|
457 | *out = data_blob_talloc(mem_ctx, in->data, in->length);
|
---|
458 | talloc_free(tmp_ctx);
|
---|
459 |
|
---|
460 | if (in->data && !out->data) {
|
---|
461 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
462 | }
|
---|
463 | return LDB_SUCCESS;
|
---|
464 | }
|
---|
465 | }
|
---|
466 | *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
|
---|
467 | talloc_free(tmp_ctx);
|
---|
468 |
|
---|
469 | if (!out->data) {
|
---|
470 | return LDB_ERR_OPERATIONS_ERROR;
|
---|
471 | }
|
---|
472 | return LDB_SUCCESS;
|
---|
473 | }
|
---|
474 |
|
---|
475 | static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
|
---|
476 | const struct ldb_val *v1,
|
---|
477 | const struct ldb_val *v2)
|
---|
478 | {
|
---|
479 |
|
---|
480 | int ret, ret1, ret2;
|
---|
481 | struct ldb_val v1_canon, v2_canon;
|
---|
482 | TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
|
---|
483 |
|
---|
484 | /* I could try and bail if tmp_ctx was NULL, but what return
|
---|
485 | * value would I use?
|
---|
486 | *
|
---|
487 | * It seems easier to continue on the NULL context
|
---|
488 | */
|
---|
489 | ret1 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v1, &v1_canon);
|
---|
490 | ret2 = ldif_canonicalise_objectCategory(ldb, tmp_ctx, v2, &v2_canon);
|
---|
491 |
|
---|
492 | if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
|
---|
493 | ret = data_blob_cmp(&v1_canon, &v2_canon);
|
---|
494 | } else {
|
---|
495 | ret = data_blob_cmp(v1, v2);
|
---|
496 | }
|
---|
497 | talloc_free(tmp_ctx);
|
---|
498 | return ret;
|
---|
499 | }
|
---|
500 |
|
---|
501 | /*
|
---|
502 | convert a ldif formatted prefixMap to a NDR formatted blob
|
---|
503 | */
|
---|
504 | static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
|
---|
505 | const struct ldb_val *in, struct ldb_val *out)
|
---|
506 | {
|
---|
507 | struct prefixMapBlob *blob;
|
---|
508 | enum ndr_err_code ndr_err;
|
---|
509 | char *string, *line, *p, *oid;
|
---|
510 |
|
---|
511 | TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
|
---|
512 |
|
---|
513 | if (tmp_ctx == NULL) {
|
---|
514 | return -1;
|
---|
515 | }
|
---|
516 |
|
---|
517 | blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
|
---|
518 | if (blob == NULL) {
|
---|
519 | talloc_free(blob);
|
---|
520 | return -1;
|
---|
521 | }
|
---|
522 |
|
---|
523 | blob->version = PREFIX_MAP_VERSION_DSDB;
|
---|
524 |
|
---|
525 | string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
|
---|
526 | if (string == NULL) {
|
---|
527 | talloc_free(blob);
|
---|
528 | return -1;
|
---|
529 | }
|
---|
530 |
|
---|
531 | line = string;
|
---|
532 | while (line && line[0]) {
|
---|
533 | p=strchr(line, ';');
|
---|
534 | if (p) {
|
---|
535 | p[0] = '\0';
|
---|
536 | } else {
|
---|
537 | p=strchr(line, '\n');
|
---|
538 | if (p) {
|
---|
539 | p[0] = '\0';
|
---|
540 | }
|
---|
541 | }
|
---|
542 | /* allow a traling seperator */
|
---|
543 | if (line == p) {
|
---|
544 | break;
|
---|
545 | }
|
---|
546 |
|
---|
547 | blob->ctr.dsdb.mappings = talloc_realloc(blob,
|
---|
548 | blob->ctr.dsdb.mappings,
|
---|
549 | struct drsuapi_DsReplicaOIDMapping,
|
---|
550 | blob->ctr.dsdb.num_mappings+1);
|
---|
551 | if (!blob->ctr.dsdb.mappings) {
|
---|
552 | talloc_free(tmp_ctx);
|
---|
553 | return -1;
|
---|
554 | }
|
---|
555 |
|
---|
556 | blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix = strtoul(line, &oid, 10);
|
---|
557 |
|
---|
558 | if (oid[0] != ':') {
|
---|
559 | talloc_free(tmp_ctx);
|
---|
560 | return -1;
|
---|
561 | }
|
---|
562 |
|
---|
563 | /* we know there must be at least ":" */
|
---|
564 | oid++;
|
---|
565 |
|
---|
566 | blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.oid
|
---|
567 | = talloc_strdup(blob->ctr.dsdb.mappings, oid);
|
---|
568 |
|
---|
569 | blob->ctr.dsdb.num_mappings++;
|
---|
570 |
|
---|
571 | /* Now look past the terminator we added above */
|
---|
572 | if (p) {
|
---|
573 | line = p + 1;
|
---|
574 | } else {
|
---|
575 | line = NULL;
|
---|
576 | }
|
---|
577 | }
|
---|
578 |
|
---|
579 | ndr_err = ndr_push_struct_blob(out, mem_ctx,
|
---|
580 | lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
|
---|
581 | blob,
|
---|
582 | (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
|
---|
583 | talloc_free(tmp_ctx);
|
---|
584 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
585 | return -1;
|
---|
586 | }
|
---|
587 | return 0;
|
---|
588 | }
|
---|
589 |
|
---|
590 | /*
|
---|
591 | convert a NDR formatted blob to a ldif formatted prefixMap
|
---|
592 | */
|
---|
593 | static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
|
---|
594 | const struct ldb_val *in, struct ldb_val *out)
|
---|
595 | {
|
---|
596 | struct prefixMapBlob *blob;
|
---|
597 | enum ndr_err_code ndr_err;
|
---|
598 | char *string;
|
---|
599 | uint32_t i;
|
---|
600 |
|
---|
601 | if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
|
---|
602 | return ldif_write_NDR(ldb, mem_ctx, in, out,
|
---|
603 | sizeof(struct prefixMapBlob),
|
---|
604 | (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
|
---|
605 | (ndr_print_fn_t)ndr_print_prefixMapBlob);
|
---|
606 |
|
---|
607 | }
|
---|
608 |
|
---|
609 | blob = talloc(mem_ctx, struct prefixMapBlob);
|
---|
610 | if (blob == NULL) {
|
---|
611 | return -1;
|
---|
612 | }
|
---|
613 | ndr_err = ndr_pull_struct_blob_all(in, blob,
|
---|
614 | lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
|
---|
615 | blob,
|
---|
616 | (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
|
---|
617 | if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
---|
618 | talloc_free(blob);
|
---|
619 | return -1;
|
---|
620 | }
|
---|
621 | if (blob->version != PREFIX_MAP_VERSION_DSDB) {
|
---|
622 | return -1;
|
---|
623 | }
|
---|
624 | string = talloc_strdup(mem_ctx, "");
|
---|
625 | if (string == NULL) {
|
---|
626 | return -1;
|
---|
627 | }
|
---|
628 |
|
---|
629 | for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
|
---|
630 | if (i > 0) {
|
---|
631 | string = talloc_asprintf_append(string, ";");
|
---|
632 | }
|
---|
633 | string = talloc_asprintf_append(string, "%u:%s",
|
---|
634 | blob->ctr.dsdb.mappings[i].id_prefix,
|
---|
635 | blob->ctr.dsdb.mappings[i].oid.oid);
|
---|
636 | if (string == NULL) {
|
---|
637 | return -1;
|
---|
638 | }
|
---|
639 | }
|
---|
640 |
|
---|
641 | talloc_free(blob);
|
---|
642 | *out = data_blob_string_const(string);
|
---|
643 | return 0;
|
---|
644 | }
|
---|
645 |
|
---|
646 | static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
|
---|
647 | {
|
---|
648 | if (v->length < 4) {
|
---|
649 | return true;
|
---|
650 | }
|
---|
651 |
|
---|
652 | if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
|
---|
653 | return false;
|
---|
654 | }
|
---|
655 |
|
---|
656 | return true;
|
---|
657 | }
|
---|
658 |
|
---|
659 | /*
|
---|
660 | canonicalise a prefixMap
|
---|
661 | */
|
---|
662 | static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
|
---|
663 | const struct ldb_val *in, struct ldb_val *out)
|
---|
664 | {
|
---|
665 | if (ldif_comparision_prefixMap_isString(in)) {
|
---|
666 | return ldif_read_prefixMap(ldb, mem_ctx, in, out);
|
---|
667 | }
|
---|
668 | return ldb_handler_copy(ldb, mem_ctx, in, out);
|
---|
669 | }
|
---|
670 |
|
---|
671 | static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
|
---|
672 | const struct ldb_val *v1,
|
---|
673 | const struct ldb_val *v2)
|
---|
674 | {
|
---|
675 |
|
---|
676 | int ret, ret1, ret2;
|
---|
677 | struct ldb_val v1_canon, v2_canon;
|
---|
678 | TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
|
---|
679 |
|
---|
680 | /* I could try and bail if tmp_ctx was NULL, but what return
|
---|
681 | * value would I use?
|
---|
682 | *
|
---|
683 | * It seems easier to continue on the NULL context
|
---|
684 | */
|
---|
685 | ret1 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v1, &v1_canon);
|
---|
686 | ret2 = ldif_canonicalise_prefixMap(ldb, tmp_ctx, v2, &v2_canon);
|
---|
687 |
|
---|
688 | if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
|
---|
689 | ret = data_blob_cmp(&v1_canon, &v2_canon);
|
---|
690 | } else {
|
---|
691 | ret = data_blob_cmp(v1, v2);
|
---|
692 | }
|
---|
693 | talloc_free(tmp_ctx);
|
---|
694 | return ret;
|
---|
695 | }
|
---|
696 |
|
---|
697 | /* Canonicalisation of two 32-bit integers */
|
---|
698 | static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
|
---|
699 | const struct ldb_val *in, struct ldb_val *out)
|
---|
700 | {
|
---|
701 | char *end;
|
---|
702 | /* We've to use "strtoll" here to have the intended overflows.
|
---|
703 | * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
|
---|
704 | int32_t i = (int32_t) strtoll((char *)in->data, &end, 0);
|
---|
705 | if (*end != 0) {
|
---|
706 | return -1;
|
---|
707 | }
|
---|
708 | out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
|
---|
709 | if (out->data == NULL) {
|
---|
710 | return -1;
|
---|
711 | }
|
---|
712 | out->length = strlen((char *)out->data);
|
---|
713 | return 0;
|
---|
714 | }
|
---|
715 |
|
---|
716 | /* Comparison of two 32-bit integers */
|
---|
717 | static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
|
---|
718 | const struct ldb_val *v1, const struct ldb_val *v2)
|
---|
719 | {
|
---|
720 | /* We've to use "strtoll" here to have the intended overflows.
|
---|
721 | * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
|
---|
722 | return (int32_t) strtoll((char *)v1->data, NULL, 0)
|
---|
723 | - (int32_t) strtoll((char *)v2->data, NULL, 0);
|
---|
724 | }
|
---|
725 |
|
---|
726 | /*
|
---|
727 | convert a NDR formatted blob to a ldif formatted repsFromTo
|
---|
728 | */
|
---|
729 | static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
|
---|
730 | const struct ldb_val *in, struct ldb_val *out)
|
---|
731 | {
|
---|
732 | return ldif_write_NDR(ldb, mem_ctx, in, out,
|
---|
733 | sizeof(struct repsFromToBlob),
|
---|
734 | (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
|
---|
735 | (ndr_print_fn_t)ndr_print_repsFromToBlob);
|
---|
736 | }
|
---|
737 |
|
---|
738 | /*
|
---|
739 | convert a NDR formatted blob to a ldif formatted replPropertyMetaData
|
---|
740 | */
|
---|
741 | static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
|
---|
742 | const struct ldb_val *in, struct ldb_val *out)
|
---|
743 | {
|
---|
744 | return ldif_write_NDR(ldb, mem_ctx, in, out,
|
---|
745 | sizeof(struct replPropertyMetaDataBlob),
|
---|
746 | (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
|
---|
747 | (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob);
|
---|
748 | }
|
---|
749 |
|
---|
750 | /*
|
---|
751 | convert a NDR formatted blob to a ldif formatted replUpToDateVector
|
---|
752 | */
|
---|
753 | static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
|
---|
754 | const struct ldb_val *in, struct ldb_val *out)
|
---|
755 | {
|
---|
756 | return ldif_write_NDR(ldb, mem_ctx, in, out,
|
---|
757 | sizeof(struct replUpToDateVectorBlob),
|
---|
758 | (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
|
---|
759 | (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob);
|
---|
760 | }
|
---|
761 |
|
---|
762 |
|
---|
763 | static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
|
---|
764 | const struct ldb_val *in, struct ldb_val *out)
|
---|
765 | {
|
---|
766 | *out = data_blob_string_const(data_blob_hex_string(mem_ctx, in));
|
---|
767 | if (!out->data) {
|
---|
768 | return -1;
|
---|
769 | }
|
---|
770 | return 0;
|
---|
771 | }
|
---|
772 |
|
---|
773 | static const struct ldb_schema_syntax samba_syntaxes[] = {
|
---|
774 | {
|
---|
775 | .name = LDB_SYNTAX_SAMBA_SID,
|
---|
776 | .ldif_read_fn = ldif_read_objectSid,
|
---|
777 | .ldif_write_fn = ldif_write_objectSid,
|
---|
778 | .canonicalise_fn = ldif_canonicalise_objectSid,
|
---|
779 | .comparison_fn = ldif_comparison_objectSid
|
---|
780 | },{
|
---|
781 | .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
|
---|
782 | .ldif_read_fn = ldif_read_ntSecurityDescriptor,
|
---|
783 | .ldif_write_fn = ldif_write_ntSecurityDescriptor,
|
---|
784 | .canonicalise_fn = ldb_handler_copy,
|
---|
785 | .comparison_fn = ldb_comparison_binary
|
---|
786 | },{
|
---|
787 | .name = LDB_SYNTAX_SAMBA_GUID,
|
---|
788 | .ldif_read_fn = ldif_read_objectGUID,
|
---|
789 | .ldif_write_fn = ldif_write_objectGUID,
|
---|
790 | .canonicalise_fn = ldif_canonicalise_objectGUID,
|
---|
791 | .comparison_fn = ldif_comparison_objectGUID
|
---|
792 | },{
|
---|
793 | .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
|
---|
794 | .ldif_read_fn = ldb_handler_copy,
|
---|
795 | .ldif_write_fn = ldb_handler_copy,
|
---|
796 | .canonicalise_fn = ldif_canonicalise_objectCategory,
|
---|
797 | .comparison_fn = ldif_comparison_objectCategory
|
---|
798 | },{
|
---|
799 | .name = LDB_SYNTAX_SAMBA_PREFIX_MAP,
|
---|
800 | .ldif_read_fn = ldif_read_prefixMap,
|
---|
801 | .ldif_write_fn = ldif_write_prefixMap,
|
---|
802 | .canonicalise_fn = ldif_canonicalise_prefixMap,
|
---|
803 | .comparison_fn = ldif_comparison_prefixMap
|
---|
804 | },{
|
---|
805 | .name = LDB_SYNTAX_SAMBA_INT32,
|
---|
806 | .ldif_read_fn = ldb_handler_copy,
|
---|
807 | .ldif_write_fn = ldb_handler_copy,
|
---|
808 | .canonicalise_fn = ldif_canonicalise_int32,
|
---|
809 | .comparison_fn = ldif_comparison_int32
|
---|
810 | },{
|
---|
811 | .name = LDB_SYNTAX_SAMBA_REPSFROMTO,
|
---|
812 | .ldif_read_fn = ldb_handler_copy,
|
---|
813 | .ldif_write_fn = ldif_write_repsFromTo,
|
---|
814 | .canonicalise_fn = ldb_handler_copy,
|
---|
815 | .comparison_fn = ldb_comparison_binary
|
---|
816 | },{
|
---|
817 | .name = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
|
---|
818 | .ldif_read_fn = ldb_handler_copy,
|
---|
819 | .ldif_write_fn = ldif_write_replPropertyMetaData,
|
---|
820 | .canonicalise_fn = ldb_handler_copy,
|
---|
821 | .comparison_fn = ldb_comparison_binary
|
---|
822 | },{
|
---|
823 | .name = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
|
---|
824 | .ldif_read_fn = ldb_handler_copy,
|
---|
825 | .ldif_write_fn = ldif_write_replUpToDateVector,
|
---|
826 | .canonicalise_fn = ldb_handler_copy,
|
---|
827 | .comparison_fn = ldb_comparison_binary
|
---|
828 | },
|
---|
829 | };
|
---|
830 |
|
---|
831 | static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
|
---|
832 | {
|
---|
833 | .name = "SID",
|
---|
834 | .read_fn = extended_dn_read_SID,
|
---|
835 | .write_clear_fn = ldif_write_objectSid,
|
---|
836 | .write_hex_fn = extended_dn_write_hex
|
---|
837 | },{
|
---|
838 | .name = "GUID",
|
---|
839 | .read_fn = extended_dn_read_GUID,
|
---|
840 | .write_clear_fn = ldif_write_objectGUID,
|
---|
841 | .write_hex_fn = extended_dn_write_hex
|
---|
842 | },{
|
---|
843 | .name = "WKGUID",
|
---|
844 | .read_fn = ldb_handler_copy,
|
---|
845 | .write_clear_fn = ldb_handler_copy,
|
---|
846 | .write_hex_fn = ldb_handler_copy
|
---|
847 | }
|
---|
848 | };
|
---|
849 |
|
---|
850 | /* TODO: Should be dynamic at some point */
|
---|
851 | static const struct {
|
---|
852 | const char *name;
|
---|
853 | const char *syntax;
|
---|
854 | } samba_attributes[] = {
|
---|
855 | { "objectSid", LDB_SYNTAX_SAMBA_SID },
|
---|
856 | { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
|
---|
857 | { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
|
---|
858 | { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
859 | { "invocationId", LDB_SYNTAX_SAMBA_GUID },
|
---|
860 | { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
861 | { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
862 | { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
863 | { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
864 | { "pKTGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
865 | { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
866 | { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
867 | { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
|
---|
868 | { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
|
---|
869 | { "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP },
|
---|
870 | { "repsFrom", LDB_SYNTAX_SAMBA_REPSFROMTO },
|
---|
871 | { "repsTo", LDB_SYNTAX_SAMBA_REPSFROMTO },
|
---|
872 | { "replPropertyMetaData", LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
|
---|
873 | { "replUpToDateVector", LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
|
---|
874 | };
|
---|
875 |
|
---|
876 | const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
|
---|
877 | {
|
---|
878 | uint32_t j;
|
---|
879 | const struct ldb_schema_syntax *s = NULL;
|
---|
880 |
|
---|
881 | for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
|
---|
882 | if (strcmp(name, samba_syntaxes[j].name) == 0) {
|
---|
883 | s = &samba_syntaxes[j];
|
---|
884 | break;
|
---|
885 | }
|
---|
886 | }
|
---|
887 | return s;
|
---|
888 | }
|
---|
889 |
|
---|
890 | const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
|
---|
891 | {
|
---|
892 | uint32_t j;
|
---|
893 | const struct ldb_schema_syntax *s = NULL;
|
---|
894 |
|
---|
895 | for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
|
---|
896 | if (strcmp(samba_attributes[j].name, name) == 0) {
|
---|
897 | s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
|
---|
898 | break;
|
---|
899 | }
|
---|
900 | }
|
---|
901 |
|
---|
902 | return s;
|
---|
903 | }
|
---|
904 |
|
---|
905 | /*
|
---|
906 | register the samba ldif handlers
|
---|
907 | */
|
---|
908 | int ldb_register_samba_handlers(struct ldb_context *ldb)
|
---|
909 | {
|
---|
910 | uint32_t i;
|
---|
911 |
|
---|
912 | for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
|
---|
913 | int ret;
|
---|
914 | const struct ldb_schema_syntax *s = NULL;
|
---|
915 |
|
---|
916 | s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
|
---|
917 |
|
---|
918 | if (!s) {
|
---|
919 | s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
|
---|
920 | }
|
---|
921 |
|
---|
922 | if (!s) {
|
---|
923 | return -1;
|
---|
924 | }
|
---|
925 |
|
---|
926 | ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
|
---|
927 | if (ret != LDB_SUCCESS) {
|
---|
928 | return ret;
|
---|
929 | }
|
---|
930 | }
|
---|
931 |
|
---|
932 | for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
|
---|
933 | int ret;
|
---|
934 | ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
|
---|
935 | if (ret != LDB_SUCCESS) {
|
---|
936 | return ret;
|
---|
937 | }
|
---|
938 |
|
---|
939 |
|
---|
940 | }
|
---|
941 |
|
---|
942 | return LDB_SUCCESS;
|
---|
943 | }
|
---|