Merge tag 'upstream/4.0.5+dfsg1' into samba_4.0_ivo
[abartlet/samba-debian.git] / lib / ldb-samba / ldif_handlers.c
similarity index 87%
rename from source4/lib/ldb-samba/ldif_handlers.c
rename to lib/ldb-samba/ldif_handlers.c
index af3c4b46e17f5fe4c8b5ac4e2937608dc5617328..c7385f654a850e31fa9f5f9155e56e2ff63ff09d 100644 (file)
@@ -27,6 +27,7 @@
 #include <ldb_module.h>
 #include "ldb_handlers.h"
 #include "dsdb/samdb/samdb.h"
+#include "dsdb/common/util.h"
 #include "librpc/gen_ndr/ndr_security.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
@@ -426,9 +427,36 @@ static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ct
        return 0;
 }
 
+/*
+  convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
+*/
+static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
+                                          const struct ldb_val *in, struct ldb_val *out)
+{
+       if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
+               struct security_descriptor *sd;
+               const struct dom_sid *sid = samdb_domain_sid(ldb);
+
+               sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
+               out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
+                                       (ndr_print_fn_t)ndr_print_security_descriptor,
+                                       "SDDL", sd);
+               out->length = strlen((const char *)out->data);
+               talloc_free(sd);
+               return 0;
+       }
+
+       return ldb_handler_copy(ldb, mem_ctx, in, out);
+}
+
 /* 
-   canonicalise an objectCategory.  We use the short form as the canonical form:
-   cn=Person,cn=Schema,cn=Configuration,<basedn> becomes 'person'
+   canonicalise an objectCategory.  We use the long form as the canonical form:
+   'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
+
+   Also any short name of an objectClass that points to a different
+   class (such as user) has the canonical form of the class it's
+   defaultObjectCategory points to (eg
+   cn=Person,cn=Schema,cn=Configuration,<basedn>)
 */
 
 static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
@@ -887,6 +915,19 @@ static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
                              true);
 }
 
+/*
+  convert a NDR formatted blob to a ldif formatted dnsProperty
+*/
+static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
+                               const struct ldb_val *in, struct ldb_val *out)
+{
+       return ldif_write_NDR(ldb, mem_ctx, in, out,
+                             sizeof(struct dnsp_DnsProperty),
+                             (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
+                             (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
+                             true);
+}
+
 /*
   convert a NDR formatted blob of a supplementalCredentials into text
 */
@@ -900,6 +941,32 @@ static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void
                              true);
 }
 
+/*
+  convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
+*/
+static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
+                                          const struct ldb_val *in, struct ldb_val *out)
+{
+       return ldif_write_NDR(ldb, mem_ctx, in, out,
+                             sizeof(struct trustAuthInOutBlob),
+                             (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
+                             (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
+                             true);
+}
+
+/*
+  convert a NDR formatted blob of a partialAttributeSet into text
+*/
+static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
+                                         const struct ldb_val *in, struct ldb_val *out)
+{
+       return ldif_write_NDR(ldb, mem_ctx, in, out,
+                             sizeof(struct partialAttributeSetBlob),
+                             (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
+                             (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
+                             true);
+}
+
 
 static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
                                 const struct ldb_val *in, struct ldb_val *out)
@@ -1073,9 +1140,9 @@ static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op o
                ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
                talloc_free(tmp_ctx);
                if (operation == LDB_OP_GREATER) {
-                       *matched = (ret > 0);
+                       *matched = (ret >= 0);
                } else if (operation == LDB_OP_LESS) {
-                       *matched = (ret < 0);
+                       *matched = (ret <= 0);
                } else {
                        *matched = (ret == 0);
                }
@@ -1091,6 +1158,65 @@ static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op o
        return LDB_ERR_INAPPROPRIATE_MATCHING;
 }
 
+/*
+  see if two DNs match, comparing first by GUID, then by SID, and
+  finally by string components
+ */
+static int samba_dn_extended_match(struct ldb_context *ldb,
+                                  const struct ldb_val *v1,
+                                  const struct ldb_val *v2,
+                                  bool *matched)
+{
+       TALLOC_CTX *tmp_ctx;
+       struct ldb_dn *dn1, *dn2;
+       const struct ldb_val *guid1, *guid2, *sid1, *sid2;
+       uint32_t rmd_flags1, rmd_flags2;
+
+       tmp_ctx = talloc_new(ldb);
+
+       dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
+       dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
+       if (!dn1 || !dn2) {
+               /* couldn't parse as DN's */
+               talloc_free(tmp_ctx);
+               (*matched) = false;
+               return LDB_SUCCESS;
+       }
+
+       rmd_flags1 = dsdb_dn_rmd_flags(dn1);
+       rmd_flags2 = dsdb_dn_rmd_flags(dn2);
+
+       if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
+           (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
+               /* only match if they have the same deletion status */
+               talloc_free(tmp_ctx);
+               (*matched) = false;
+               return LDB_SUCCESS;
+       }
+
+
+       guid1 = ldb_dn_get_extended_component(dn1, "GUID");
+       guid2 = ldb_dn_get_extended_component(dn2, "GUID");
+       if (guid1 && guid2) {
+               (*matched) = (data_blob_cmp(guid1, guid2) == 0);
+               talloc_free(tmp_ctx);
+               return LDB_SUCCESS;
+       }
+
+       sid1 = ldb_dn_get_extended_component(dn1, "SID");
+       sid2 = ldb_dn_get_extended_component(dn2, "SID");
+       if (sid1 && sid2) {
+               (*matched) = (data_blob_cmp(sid1, sid2) == 0);
+               talloc_free(tmp_ctx);
+               return LDB_SUCCESS;
+       }
+
+       (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
+
+       talloc_free(tmp_ctx);
+       return LDB_SUCCESS;
+}
+
 /*
   special operation for DNs, to take account of the RMD_FLAGS deleted bit
  */
@@ -1100,9 +1226,17 @@ static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op o
 {
        if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
                /* If the DN is deleted, then we can't search for it */
+
+               /* should this be for equality too? */
                *matched = false;
                return LDB_SUCCESS;
        }
+
+       if (operation == LDB_OP_EQUALITY &&
+           samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
+               return LDB_SUCCESS;
+       }
+
        return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
 }
 
@@ -1122,6 +1256,13 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .canonicalise_fn  = ldb_handler_copy,
                .comparison_fn    = ldb_comparison_binary,
                .operator_fn      = samba_syntax_operator_fn
+       },{
+               .name             = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
+               .ldif_read_fn     = ldb_handler_copy,
+               .ldif_write_fn    = ldif_write_sddlSecurityDescriptor,
+               .canonicalise_fn  = ldb_handler_fold,
+               .comparison_fn    = ldb_comparison_fold,
+               .operator_fn      = samba_syntax_operator_fn
        },{
                .name             = LDB_SYNTAX_SAMBA_GUID,
                .ldif_read_fn     = ldif_read_objectGUID,
@@ -1178,6 +1319,13 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .canonicalise_fn  = ldb_handler_copy,
                .comparison_fn    = ldb_comparison_binary,
                .operator_fn      = samba_syntax_operator_fn
+       },{
+               .name             = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
+               .ldif_read_fn     = ldb_handler_copy,
+               .ldif_write_fn    = ldif_write_trustAuthInOutBlob,
+               .canonicalise_fn  = ldb_handler_copy,
+               .comparison_fn    = ldb_comparison_binary,
+               .operator_fn      = samba_syntax_operator_fn
        },{
                .name             = DSDB_SYNTAX_BINARY_DN,
                .ldif_read_fn     = ldb_handler_copy,
@@ -1213,6 +1361,13 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .canonicalise_fn  = ldb_handler_copy,
                .comparison_fn    = ldb_comparison_binary,
                .operator_fn      = samba_syntax_operator_fn
+       },{
+               .name             = LDB_SYNTAX_SAMBA_DNSPROPERTY,
+               .ldif_read_fn     = ldb_handler_copy,
+               .ldif_write_fn    = ldif_write_dnsProperty,
+               .canonicalise_fn  = ldb_handler_copy,
+               .comparison_fn    = ldb_comparison_binary,
+               .operator_fn      = samba_syntax_operator_fn
        },{
                .name             = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
                .ldif_read_fn     = ldb_handler_copy,
@@ -1220,6 +1375,13 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .canonicalise_fn  = ldb_handler_copy,
                .comparison_fn    = ldb_comparison_binary,
                .operator_fn      = samba_syntax_operator_fn
+       },{
+               .name             = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
+               .ldif_read_fn     = ldb_handler_copy,
+               .ldif_write_fn    = ldif_write_partialAttributeSet,
+               .canonicalise_fn  = ldb_handler_copy,
+               .comparison_fn    = ldb_comparison_binary,
+               .operator_fn      = samba_syntax_operator_fn
        }
 };
 
@@ -1294,9 +1456,12 @@ static const struct {
        { "repsTo",                     LDB_SYNTAX_SAMBA_REPSFROMTO },
        { "replPropertyMetaData",       LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
        { "replUpToDateVector",         LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
+       { "trustAuthIncoming",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
+       { "trustAuthOutgoing",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
        { "rIDAllocationPool",          LDB_SYNTAX_SAMBA_RANGE64 },
        { "rIDPreviousAllocationPool",  LDB_SYNTAX_SAMBA_RANGE64 },
        { "rIDAvailablePool",           LDB_SYNTAX_SAMBA_RANGE64 },
+       { "defaultSecurityDescriptor",  LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
 
        /*
         * these are extracted by searching
@@ -1336,7 +1501,9 @@ static const struct {
 
        /* These NDR encoded things we want to be able to read with --show-binary */
        { "dnsRecord",                          LDB_SYNTAX_SAMBA_DNSRECORD },
-       { "supplementalCredentials",            LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS}
+       { "dNSProperty",                        LDB_SYNTAX_SAMBA_DNSPROPERTY },
+       { "supplementalCredentials",            LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
+       { "partialAttributeSet",                LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
 };
 
 const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
@@ -1368,6 +1535,8 @@ const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_c
        return s;
 }
 
+static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, NULL};
+
 /*
   register the samba ldif handlers
 */
@@ -1380,6 +1549,11 @@ int ldb_register_samba_handlers(struct ldb_context *ldb)
                return LDB_SUCCESS;
        }
 
+       ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+
        for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
                const struct ldb_schema_syntax *s = NULL;