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 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
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
)
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
;
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
);
314 oc2
= ldb_casefold(ldb
, mem_ctx
, oc1
);
315 out
->data
= (void *)oc2
;
316 out
->length
= strlen(oc2
);
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
);
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
);
349 oc1
= ldb_casefold(ldb
, mem_ctx
, oc1
);
350 oc2
= ldb_casefold(ldb
, mem_ctx
, oc2
);
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 {
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
)
437 for (i
=0; i
< ARRAY_SIZE(samba_attributes
); i
++) {
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
];
450 s
= ldb_standard_syntax_by_name(ldb
, samba_attributes
[i
].syntax
);
457 ret
= ldb_schema_attribute_add_with_syntax(ldb
, samba_attributes
[i
].name
, 0, s
);
458 if (ret
!= LDB_SUCCESS
) {