r20184: change ldb_attrib_handler into ldb_schema_attribute, which has a pointer
[Samba/ekacnet.git] / source4 / lib / ldb / samba / ldif_handlers.c
blob961312afb66264b39492ea344624a4ef30644e81
1 /*
2 ldb database library - ldif handlers for Samba
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
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.
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.
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
25 #include "includes.h"
26 #include "ldb/include/includes.h"
27 #include "ldb/include/ldb_handlers.h"
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"
35 convert a ldif formatted objectSid to a NDR formatted blob
37 static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
38 const struct ldb_val *in, struct ldb_val *out)
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;
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;
52 return 0;
56 convert a NDR formatted blob to a ldif formatted objectSid
58 static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
59 const struct ldb_val *in, struct ldb_val *out)
61 struct dom_sid *sid;
62 NTSTATUS status;
63 sid = talloc(mem_ctx, struct dom_sid);
64 if (sid == NULL) {
65 return -1;
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;
73 out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
74 talloc_free(sid);
75 if (out->data == NULL) {
76 return -1;
78 out->length = strlen((const char *)out->data);
79 return 0;
82 static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v)
84 if (v->length < 3) {
85 return False;
88 if (strncmp("S-", (const char *)v->data, 2) != 0) return False;
90 return True;
94 compare two objectSids
96 static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
97 const struct ldb_val *v1, const struct ldb_val *v2)
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;
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;
118 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
119 talloc_free(v.data);
120 return ret;
122 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
126 canonicalise a objectSid
128 static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
129 const struct ldb_val *in, struct ldb_val *out)
131 if (ldb_comparision_objectSid_isString(in)) {
132 return ldif_read_objectSid(ldb, mem_ctx, in, out);
134 return ldb_handler_copy(ldb, mem_ctx, in, out);
138 convert a ldif formatted objectGUID to a NDR formatted blob
140 static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
141 const struct ldb_val *in, struct ldb_val *out)
143 struct GUID guid;
144 NTSTATUS status;
146 status = GUID_from_string((const char *)in->data, &guid);
147 if (!NT_STATUS_IS_OK(status)) {
148 return -1;
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;
156 return 0;
160 convert a NDR formatted blob to a ldif formatted objectGUID
162 static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
163 const struct ldb_val *in, struct ldb_val *out)
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;
172 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
173 if (out->data == NULL) {
174 return -1;
176 out->length = strlen((const char *)out->data);
177 return 0;
180 static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v)
182 struct GUID guid;
183 NTSTATUS status;
185 if (v->length < 33) return False;
187 /* see if the input if null-terninated (safety check for the below) */
188 if (v->data[v->length] != '\0') return False;
190 status = GUID_from_string((const char *)v->data, &guid);
191 if (!NT_STATUS_IS_OK(status)) {
192 return False;
195 return True;
199 compare two objectGUIDs
201 static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
202 const struct ldb_val *v1, const struct ldb_val *v2)
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;
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;
223 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
224 talloc_free(v.data);
225 return ret;
227 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
231 canonicalise a objectGUID
233 static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
234 const struct ldb_val *in, struct ldb_val *out)
236 if (ldb_comparision_objectGUID_isString(in)) {
237 return ldif_read_objectGUID(ldb, mem_ctx, in, out);
239 return ldb_handler_copy(ldb, mem_ctx, in, out);
244 convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
246 static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
247 const struct ldb_val *in, struct ldb_val *out)
249 struct security_descriptor *sd;
250 NTSTATUS status;
252 sd = sddl_decode(mem_ctx, (const char *)in->data, NULL);
253 if (sd == NULL) {
254 return -1;
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;
262 return 0;
266 convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
268 static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
269 const struct ldb_val *in, struct ldb_val *out)
271 struct security_descriptor *sd;
272 NTSTATUS status;
274 sd = talloc(mem_ctx, struct security_descriptor);
275 if (sd == NULL) {
276 return -1;
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;
284 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);
285 talloc_free(sd);
286 if (out->data == NULL) {
287 return -1;
289 out->length = strlen((const char *)out->data);
290 return 0;
294 canonicolise an objectCategory. We use the short form as the cannoical form:
295 cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
298 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
299 const struct ldb_val *in, struct ldb_val *out)
301 struct ldb_dn *dn1 = NULL;
302 char *oc1, *oc2;
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;
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;
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)
326 struct ldb_dn *dn1 = NULL, *dn2 = NULL;
327 const char *oc1, *oc2;
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;
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;
349 oc1 = ldb_casefold(ldb, mem_ctx, oc1);
350 oc2 = ldb_casefold(ldb, mem_ctx, oc2);
351 if (!oc1 && oc2) {
352 return -1;
354 if (oc1 && !oc2) {
355 return 1;
357 if (!oc1 && !oc2) {
358 return -1;
361 return strcmp(oc1, oc2);
364 #define LDB_SYNTAX_SAMBA_SID "LDB_SYNTAX_SAMBA_SID"
365 #define LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR "LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR"
366 #define LDB_SYNTAX_SAMBA_GUID "LDB_SYNTAX_SAMBA_GUID"
367 #define LDB_SYNTAX_SAMBA_OBJECT_CATEGORY "LDB_SYNTAX_SAMBA_OBJECT_CATEGORY"
369 static const struct ldb_schema_syntax samba_syntaxes[] = {
371 .name = LDB_SYNTAX_SAMBA_SID,
372 .ldif_read_fn = ldif_read_objectSid,
373 .ldif_write_fn = ldif_write_objectSid,
374 .canonicalise_fn= ldb_canonicalise_objectSid,
375 .comparison_fn = ldb_comparison_objectSid
377 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
378 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
379 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
380 .canonicalise_fn= ldb_handler_copy,
381 .comparison_fn = ldb_comparison_binary
383 .name = LDB_SYNTAX_SAMBA_GUID,
384 .ldif_read_fn = ldif_read_objectGUID,
385 .ldif_write_fn = ldif_write_objectGUID,
386 .canonicalise_fn= ldb_canonicalise_objectGUID,
387 .comparison_fn = ldb_comparison_objectGUID
389 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
390 .ldif_read_fn = ldb_handler_copy,
391 .ldif_write_fn = ldb_handler_copy,
392 .canonicalise_fn= ldif_canonicalise_objectCategory,
393 .comparison_fn = ldif_comparison_objectCategory
397 static const struct {
398 const char *name;
399 const char *syntax;
400 } samba_attributes[] = {
401 { "objectSid", LDB_SYNTAX_SAMBA_SID },
402 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
403 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
404 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
405 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
406 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
407 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
408 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
409 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
410 { "pKTGUID", LDB_SYNTAX_SAMBA_GUID },
411 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
412 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
413 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
414 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
415 { "member", LDB_SYNTAX_DN },
416 { "memberOf", LDB_SYNTAX_DN },
417 { "nCName", LDB_SYNTAX_DN },
418 { "schemaNamingContext", LDB_SYNTAX_DN },
419 { "configurationNamingContext", LDB_SYNTAX_DN },
420 { "rootDomainNamingContext", LDB_SYNTAX_DN },
421 { "defaultNamingContext", LDB_SYNTAX_DN },
422 { "subRefs", LDB_SYNTAX_DN },
423 { "dMDLocation", LDB_SYNTAX_DN },
424 { "serverReference", LDB_SYNTAX_DN },
425 { "masteredBy", LDB_SYNTAX_DN },
426 { "msDs-masteredBy", LDB_SYNTAX_DN },
427 { "fSMORoleOwner", LDB_SYNTAX_DN },
431 register the samba ldif handlers
433 int ldb_register_samba_handlers(struct ldb_context *ldb)
435 uint32_t i;
437 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
438 int ret;
439 uint32_t j;
440 struct ldb_schema_syntax *s = NULL;
442 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
443 if (strcmp(samba_attributes[i].syntax, samba_syntaxes[j].name) == 0) {
444 s = &samba_syntaxes[j];
445 break;
449 if (!s) {
450 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
453 if (!s) {
454 return -1;
457 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, 0, s);
458 if (ret != LDB_SUCCESS) {
459 return ret;
463 return LDB_SUCCESS;