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
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.
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
26 #include "ldb_includes.h"
27 #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)
42 sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data);
46 status = ndr_push_struct_blob(out, mem_ctx, sid,
47 (ndr_push_flags_fn_t)ndr_push_dom_sid);
49 if (!NT_STATUS_IS_OK(status)) {
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)
63 sid = talloc(mem_ctx, struct dom_sid);
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)) {
73 out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
75 if (out->data == NULL) {
78 out->length = strlen((const char *)out->data);
82 static BOOL ldb_comparision_objectSid_isString(const struct ldb_val *v)
88 if (strncmp("S-", (const char *)v->data, 2) != 0) return False;
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)) {
105 if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
108 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
111 } else if (!ldb_comparision_objectSid_isString(v1)
112 && ldb_comparision_objectSid_isString(v2)) {
115 if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
118 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
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)
146 status = GUID_from_string((const char *)in->data, &guid);
147 if (!NT_STATUS_IS_OK(status)) {
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)) {
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)
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)) {
172 out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
173 if (out->data == NULL) {
176 out->length = strlen((const char *)out->data);
180 static BOOL ldb_comparision_objectGUID_isString(const struct ldb_val *v)
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)) {
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)) {
210 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
213 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
216 } else if (!ldb_comparision_objectGUID_isString(v1)
217 && ldb_comparision_objectGUID_isString(v2)) {
220 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
223 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
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;
252 sd = sddl_decode(mem_ctx, (const char *)in->data, NULL);
256 status = ndr_push_struct_blob(out, mem_ctx, sd,
257 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
259 if (!NT_STATUS_IS_OK(status)) {
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;
274 sd = talloc(mem_ctx, struct security_descriptor);
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)) {
284 out->data = (uint8_t *)sddl_encode(mem_ctx, sd, NULL);
286 if (out->data == NULL) {
289 out->length = strlen((const char *)out->data);
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 const struct dsdb_schema *schema = dsdb_get_schema(ldb);
303 const struct dsdb_class *class;
306 *out = data_blob_talloc(mem_ctx, in->data, in->length);
309 dn1 = ldb_dn_new(mem_ctx, ldb, (char *)in->data);
310 if ( ! ldb_dn_validate(dn1)) {
311 const char *lDAPDisplayName = talloc_strndup(mem_ctx, (char *)in->data, in->length);
312 class = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
313 talloc_free(lDAPDisplayName);
314 } else if (ldb_dn_get_comp_num(dn1) >= 1 && ldb_attr_cmp(ldb_dn_get_rdn_name(dn1), "cn") == 0) {
315 const struct ldb_val *val = ldb_dn_get_rdn_val(dn1);
316 const char *cn = talloc_strndup(mem_ctx, (char *)val->data, val->length);
317 class = dsdb_class_by_cn(schema, cn);
329 *out = data_blob_string_const(talloc_strdup(mem_ctx, class->lDAPDisplayName));
334 static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
335 const struct ldb_val *v1,
336 const struct ldb_val *v2)
340 struct ldb_val v1_canon, v2_canon;
341 ret1 = ldif_canonicalise_objectCategory(ldb, mem_ctx, v1, &v1_canon);
342 ret2 = ldif_canonicalise_objectCategory(ldb, mem_ctx, v2, &v2_canon);
344 if (ret1 == LDB_SUCCESS && ret2 == LDB_SUCCESS) {
345 return ldb_attr_cmp(v1_canon.data, v2_canon.data);
347 return strcasecmp(v1->data, v2->data);
351 #define LDB_SYNTAX_SAMBA_SID "LDB_SYNTAX_SAMBA_SID"
352 #define LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR "LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR"
353 #define LDB_SYNTAX_SAMBA_GUID "LDB_SYNTAX_SAMBA_GUID"
354 #define LDB_SYNTAX_SAMBA_OBJECT_CATEGORY "LDB_SYNTAX_SAMBA_OBJECT_CATEGORY"
356 static const struct ldb_schema_syntax samba_syntaxes[] = {
358 .name = LDB_SYNTAX_SAMBA_SID,
359 .ldif_read_fn = ldif_read_objectSid,
360 .ldif_write_fn = ldif_write_objectSid,
361 .canonicalise_fn= ldb_canonicalise_objectSid,
362 .comparison_fn = ldb_comparison_objectSid
364 .name = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
365 .ldif_read_fn = ldif_read_ntSecurityDescriptor,
366 .ldif_write_fn = ldif_write_ntSecurityDescriptor,
367 .canonicalise_fn= ldb_handler_copy,
368 .comparison_fn = ldb_comparison_binary
370 .name = LDB_SYNTAX_SAMBA_GUID,
371 .ldif_read_fn = ldif_read_objectGUID,
372 .ldif_write_fn = ldif_write_objectGUID,
373 .canonicalise_fn= ldb_canonicalise_objectGUID,
374 .comparison_fn = ldb_comparison_objectGUID
376 .name = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
377 .ldif_read_fn = ldb_handler_copy,
378 .ldif_write_fn = ldb_handler_copy,
379 .canonicalise_fn= ldif_canonicalise_objectCategory,
380 .comparison_fn = ldif_comparison_objectCategory
384 static const struct {
387 } samba_attributes[] = {
388 { "objectSid", LDB_SYNTAX_SAMBA_SID },
389 { "securityIdentifier", LDB_SYNTAX_SAMBA_SID },
390 { "ntSecurityDescriptor", LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
391 { "objectGUID", LDB_SYNTAX_SAMBA_GUID },
392 { "invocationId", LDB_SYNTAX_SAMBA_GUID },
393 { "schemaIDGUID", LDB_SYNTAX_SAMBA_GUID },
394 { "attributeSecurityGUID", LDB_SYNTAX_SAMBA_GUID },
395 { "parentGUID", LDB_SYNTAX_SAMBA_GUID },
396 { "siteGUID", LDB_SYNTAX_SAMBA_GUID },
397 { "pKTGUID", LDB_SYNTAX_SAMBA_GUID },
398 { "fRSVersionGUID", LDB_SYNTAX_SAMBA_GUID },
399 { "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
400 { "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
401 { "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
402 { "member", LDB_SYNTAX_DN },
403 { "memberOf", LDB_SYNTAX_DN },
404 { "nCName", LDB_SYNTAX_DN },
405 { "schemaNamingContext", LDB_SYNTAX_DN },
406 { "configurationNamingContext", LDB_SYNTAX_DN },
407 { "rootDomainNamingContext", LDB_SYNTAX_DN },
408 { "defaultNamingContext", LDB_SYNTAX_DN },
409 { "subRefs", LDB_SYNTAX_DN },
410 { "dMDLocation", LDB_SYNTAX_DN },
411 { "serverReference", LDB_SYNTAX_DN },
412 { "masteredBy", LDB_SYNTAX_DN },
413 { "msDs-masteredBy", LDB_SYNTAX_DN },
414 { "fSMORoleOwner", LDB_SYNTAX_DN },
418 register the samba ldif handlers
420 int ldb_register_samba_handlers(struct ldb_context *ldb)
424 for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
427 const struct ldb_schema_syntax *s = NULL;
429 for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
430 if (strcmp(samba_attributes[i].syntax, samba_syntaxes[j].name) == 0) {
431 s = &samba_syntaxes[j];
437 s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
444 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, 0, s);
445 if (ret != LDB_SUCCESS) {