ldb-samba: Add "secret" as a value to hide in LDIF files
[samba.git] / lib / ldb-samba / ldif_handlers.c
index 52c77bd5a24637afc1228ddd8b3498aced3c2cee..87c171e28d292efe3cd5697975172cae9417570d 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"
@@ -105,21 +106,15 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
 int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
                                const struct ldb_val *in, struct ldb_val *out)
 {
-       struct dom_sid *sid;
+       struct dom_sid sid;
        enum ndr_err_code ndr_err;
 
-       sid = talloc(mem_ctx, struct dom_sid);
-       if (sid == NULL) {
-               return -1;
-       }
-       ndr_err = ndr_pull_struct_blob_all(in, sid, sid,
+       ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
                                           (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-               talloc_free(sid);
                return -1;
        }
-       *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
-       talloc_free(sid);
+       *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
        if (out->data == NULL) {
                return -1;
        }
@@ -209,7 +204,7 @@ static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
                                     (const char *)in->data, in->length);
 
        /* Check it looks like a SID */
-       ndr_err = ndr_pull_struct_blob_all(out, mem_ctx, &sid,
+       ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
                                           (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return -1;
@@ -482,8 +477,13 @@ static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_c
                const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
                sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
                if (sclass) {
-                       struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb,  
+                       struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
                                                       sclass->defaultObjectCategory);
+                       if (dn == NULL) {
+                               talloc_free(tmp_ctx);
+                               return LDB_ERR_OPERATIONS_ERROR;
+                       }
+
                        *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
                        talloc_free(tmp_ctx);
 
@@ -900,6 +900,69 @@ static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
                              true);
 }
 
+static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
+                                   const struct ldb_val *in, struct ldb_val *out,
+                                   size_t struct_size,
+                                   ndr_pull_flags_fn_t pull_fn,
+                                   ndr_print_fn_t print_fn,
+                                   bool mask_errors)
+{
+       uint8_t *p = NULL;
+       enum ndr_err_code err;
+       struct dsdb_dn *dsdb_dn = NULL;
+       char *dn_str = NULL;
+       char *str = NULL;
+
+       if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
+               return ldb_handler_copy(ldb, mem_ctx, in, out);
+       }
+
+       dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
+       if (dsdb_dn == NULL) {
+               return ldb_handler_copy(ldb, mem_ctx, in, out);
+       }
+
+       p = talloc_size(dsdb_dn, struct_size);
+       if (p == NULL) {
+               TALLOC_FREE(dsdb_dn);
+               return ldb_handler_copy(ldb, mem_ctx, in, out);
+       }
+
+       err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
+       if (err != NDR_ERR_SUCCESS) {
+               /* fail in not in mask_error mode */
+               if (!mask_errors) {
+                       return -1;
+               }
+               TALLOC_FREE(dsdb_dn);
+               return ldb_handler_copy(ldb, mem_ctx, in, out);
+       }
+
+       dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
+       if (dn_str == NULL) {
+               TALLOC_FREE(dsdb_dn);
+               return ldb_handler_copy(ldb, mem_ctx, in, out);
+       }
+
+       str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
+       TALLOC_FREE(dsdb_dn);
+       if (str == NULL) {
+               return ldb_handler_copy(ldb, mem_ctx, in, out);
+       }
+
+       *out = data_blob_string_const(str);
+       return 0;
+}
+
+static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
+                                        const struct ldb_val *in, struct ldb_val *out)
+{
+       return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
+                             sizeof(struct replPropertyMetaData1),
+                             (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
+                             (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
+                             true);
+}
 
 /*
   convert a NDR formatted blob to a ldif formatted dnsRecord
@@ -914,6 +977,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
 */
@@ -940,6 +1016,18 @@ static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
                              true);
 }
 
+/*
+  convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
+*/
+static int ldif_write_ForestTrustInfo(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 ForestTrustInfo),
+                             (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
+                             (ndr_print_fn_t)ndr_print_ForestTrustInfo,
+                             true);
+}
 /*
   convert a NDR formatted blob of a partialAttributeSet into text
 */
@@ -1126,9 +1214,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);
                }
@@ -1144,6 +1232,47 @@ static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op o
        return LDB_ERR_INAPPROPRIATE_MATCHING;
 }
 
+/*
+  compare two binary objects.  This is correct for sorting as the sort order is:
+  
+  a
+  aa
+  b
+  bb
+
+  rather than ldb_comparison_binary() which is:
+
+  a
+  b
+  aa
+  bb
+  
+*/
+static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
+                                      const struct ldb_val *v1, const struct ldb_val *v2)
+{
+       return data_blob_cmp(v1, v2);
+}
+
+/*
+  when this operator_fn is set for a syntax, the backend calls is in
+  preference to the comparison function. We are told the exact
+  comparison operation that is needed, and we can return errors.
+
+  This mode optimises for ldb_comparison_binary() if we need equality,
+  as this should be faster as it can do a length-check first.
+ */
+static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
+                                          const struct ldb_schema_attribute *a,
+                                          const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
+{
+       if (operation == LDB_OP_EQUALITY) {
+               *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
+               return LDB_SUCCESS;
+       }
+       return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
+}
+
 /*
   see if two DNs match, comparing first by GUID, then by SID, and
   finally by string components
@@ -1240,8 +1369,8 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .ldif_read_fn     = ldif_read_ntSecurityDescriptor,
                .ldif_write_fn    = ldif_write_ntSecurityDescriptor,
                .canonicalise_fn  = ldb_handler_copy,
-               .comparison_fn    = ldb_comparison_binary,
-               .operator_fn      = samba_syntax_operator_fn
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
        },{
                .name             = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
                .ldif_read_fn     = ldb_handler_copy,
@@ -1268,8 +1397,8 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .ldif_read_fn     = ldb_handler_copy,
                .ldif_write_fn    = ldif_write_schemaInfo,
                .canonicalise_fn  = ldb_handler_copy,
-               .comparison_fn    = ldb_comparison_binary,
-               .operator_fn      = samba_syntax_operator_fn
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
        },{
                .name             = LDB_SYNTAX_SAMBA_PREFIX_MAP,
                .ldif_read_fn     = ldif_read_prefixMap,
@@ -1289,29 +1418,43 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .ldif_read_fn     = ldb_handler_copy,
                .ldif_write_fn    = ldif_write_repsFromTo,
                .canonicalise_fn  = ldb_handler_copy,
-               .comparison_fn    = ldb_comparison_binary,
-               .operator_fn      = samba_syntax_operator_fn
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
        },{
                .name             = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
                .ldif_read_fn     = ldb_handler_copy,
                .ldif_write_fn    = ldif_write_replPropertyMetaData,
                .canonicalise_fn  = ldb_handler_copy,
-               .comparison_fn    = ldb_comparison_binary,
-               .operator_fn      = samba_syntax_operator_fn
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
        },{
                .name             = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
                .ldif_read_fn     = ldb_handler_copy,
                .ldif_write_fn    = ldif_write_replUpToDateVector,
                .canonicalise_fn  = ldb_handler_copy,
-               .comparison_fn    = ldb_comparison_binary,
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
+       },{
+               .name             = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
+               .ldif_read_fn     = ldb_handler_copy,
+               .ldif_write_fn    = ldif_write_msDS_RevealedUsers,
+               .canonicalise_fn  = dsdb_dn_binary_canonicalise,
+               .comparison_fn    = dsdb_dn_binary_comparison,
                .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
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
+       },{
+               .name             = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
+               .ldif_read_fn     = ldb_handler_copy,
+               .ldif_write_fn    = ldif_write_ForestTrustInfo,
+               .canonicalise_fn  = ldb_handler_copy,
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
        },{
                .name             = DSDB_SYNTAX_BINARY_DN,
                .ldif_read_fn     = ldb_handler_copy,
@@ -1345,22 +1488,36 @@ static const struct ldb_schema_syntax samba_syntaxes[] = {
                .ldif_read_fn     = ldb_handler_copy,
                .ldif_write_fn    = ldif_write_dnsRecord,
                .canonicalise_fn  = ldb_handler_copy,
-               .comparison_fn    = ldb_comparison_binary,
-               .operator_fn      = samba_syntax_operator_fn
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_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    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
        },{
                .name             = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
                .ldif_read_fn     = ldb_handler_copy,
                .ldif_write_fn    = ldif_write_supplementalCredentialsBlob,
                .canonicalise_fn  = ldb_handler_copy,
-               .comparison_fn    = ldb_comparison_binary,
-               .operator_fn      = samba_syntax_operator_fn
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_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
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
+       },{
+               .name             = LDB_SYNTAX_SAMBA_OCTET_STRING,
+               .ldif_read_fn     = ldb_handler_copy,
+               .ldif_write_fn    = ldb_handler_copy,
+               .canonicalise_fn  = ldb_handler_copy,
+               .comparison_fn    = samba_ldb_comparison_binary,
+               .operator_fn      = samba_syntax_binary_operator_fn
        }
 };
 
@@ -1423,9 +1580,6 @@ static const struct {
        const char *name;
        const char *syntax;
 } samba_attributes[] = {
-       { "objectSid",                  LDB_SYNTAX_SAMBA_SID },
-       { "securityIdentifier",         LDB_SYNTAX_SAMBA_SID },
-       { "tokenGroups",                LDB_SYNTAX_SAMBA_SID },
        { "ntSecurityDescriptor",       LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
        { "oMSyntax",                   LDB_SYNTAX_SAMBA_INT32 },
        { "objectCategory",             LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
@@ -1435,13 +1589,35 @@ static const struct {
        { "repsTo",                     LDB_SYNTAX_SAMBA_REPSFROMTO },
        { "replPropertyMetaData",       LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
        { "replUpToDateVector",         LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
+       { "msDS-RevealedUsers",         LDB_SYNTAX_SAMBA_REVEALEDUSERS },
        { "trustAuthIncoming",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
        { "trustAuthOutgoing",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
+       { "msDS-TrustForestTrustInfo",  LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
        { "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
+        * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
+        *
+        * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
+        * adminDescription: For a Central Access Policy, this attribute defines a GUID t
+        * hat can be used to identify the set of policies when applied to a resource.
+        * Until we see a msAuthz-CentralAccessPolicyID value on a windows
+        * server, we ignore it here.
+        */
+       { "mS-DS-CreatorSID",           LDB_SYNTAX_SAMBA_SID },
+       { "msDS-QuotaTrustee",          LDB_SYNTAX_SAMBA_SID },
+       { "objectSid",                  LDB_SYNTAX_SAMBA_SID },
+       { "tokenGroups",                LDB_SYNTAX_SAMBA_SID },
+       { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
+       { "tokenGroupsNoGCAcceptable",  LDB_SYNTAX_SAMBA_SID },
+       { "securityIdentifier",         LDB_SYNTAX_SAMBA_SID },
+       { "sIDHistory",                 LDB_SYNTAX_SAMBA_SID },
+       { "syncWithSID",                LDB_SYNTAX_SAMBA_SID },
+
        /*
         * these are extracted by searching
         * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
@@ -1454,6 +1630,8 @@ static const struct {
        { "fRSVersionGUID",                     LDB_SYNTAX_SAMBA_GUID },
        { "implementedCategories",              LDB_SYNTAX_SAMBA_GUID },
        { "msDS-AzObjectGuid",                  LDB_SYNTAX_SAMBA_GUID },
+       { "msDS-GenerationId",                  LDB_SYNTAX_SAMBA_GUID },
+       { "msDS-OptionalFeatureGUID",           LDB_SYNTAX_SAMBA_GUID },
        { "msDFSR-ContentSetGuid",              LDB_SYNTAX_SAMBA_GUID },
        { "msDFSR-ReplicationGroupGuid",        LDB_SYNTAX_SAMBA_GUID },
        { "mSMQDigests",                        LDB_SYNTAX_SAMBA_GUID },
@@ -1470,16 +1648,18 @@ static const struct {
        { "msDFS-GenerationGUIDv2",             LDB_SYNTAX_SAMBA_GUID },
        { "msDFS-LinkIdentityGUIDv2",           LDB_SYNTAX_SAMBA_GUID },
        { "msDFS-NamespaceIdentityGUIDv2",      LDB_SYNTAX_SAMBA_GUID },
+       { "msSPP-CSVLKSkuId",                   LDB_SYNTAX_SAMBA_GUID },
+       { "msSPP-KMSIds",                       LDB_SYNTAX_SAMBA_GUID },
 
        /*
         * these are known to be GUIDs
         */
        { "invocationId",                       LDB_SYNTAX_SAMBA_GUID },
        { "parentGUID",                         LDB_SYNTAX_SAMBA_GUID },
-       { "msDS-OptionalFeatureGUID",           LDB_SYNTAX_SAMBA_GUID },
 
        /* These NDR encoded things we want to be able to read with --show-binary */
        { "dnsRecord",                          LDB_SYNTAX_SAMBA_DNSRECORD },
+       { "dNSProperty",                        LDB_SYNTAX_SAMBA_DNSPROPERTY },
        { "supplementalCredentials",            LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
        { "partialAttributeSet",                LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
 };
@@ -1513,6 +1693,8 @@ const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_c
        return s;
 }
 
+static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret", NULL};
+
 /*
   register the samba ldif handlers
 */
@@ -1525,6 +1707,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;
 
@@ -1552,6 +1739,12 @@ int ldb_register_samba_handlers(struct ldb_context *ldb)
 
        }
 
+       ret = ldb_register_samba_matching_rules(ldb);
+       if (ret != LDB_SUCCESS) {
+               talloc_free(ldb);
+               return LDB_SUCCESS;
+       }
+
        ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
        if (ret != LDB_SUCCESS) {
                return ret;