LCOV - code coverage report
Current view: top level - lib/ldb-samba - ldif_handlers.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 497 687 72.3 %
Date: 2024-05-31 13:13:24 Functions: 47 54 87.0 %

          Line data    Source code
       1             : /*
       2             :    ldb database library - ldif handlers for Samba
       3             : 
       4             :    Copyright (C) Andrew Tridgell 2005
       5             :    Copyright (C) Andrew Bartlett 2006-2009
       6             :    Copyright (C) Matthias Dieter Wallnöfer 2009
       7             :      ** NOTE! The following LGPL license applies to the ldb
       8             :      ** library. This does NOT imply that all of Samba is released
       9             :      ** under the LGPL
      10             : 
      11             :    This library is free software; you can redistribute it and/or
      12             :    modify it under the terms of the GNU Lesser General Public
      13             :    License as published by the Free Software Foundation; either
      14             :    version 3 of the License, or (at your option) any later version.
      15             : 
      16             :    This library is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      19             :    Lesser General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU Lesser General Public
      22             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include <ldb.h>
      27             : #include <ldb_module.h>
      28             : #include "ldb_handlers.h"
      29             : #include "dsdb/samdb/samdb.h"
      30             : #include "dsdb/common/util.h"
      31             : #include "librpc/gen_ndr/ndr_security.h"
      32             : #include "librpc/gen_ndr/ndr_misc.h"
      33             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      34             : #include "librpc/gen_ndr/ndr_dnsp.h"
      35             : #include "librpc/ndr/libndr.h"
      36             : #include "libcli/security/security.h"
      37             : #include "param/param.h"
      38             : #include "../lib/util/asn1.h"
      39             : #include "lib/util/smb_strtox.h"
      40             : 
      41             : /*
      42             :   use ndr_print_* to convert a NDR formatted blob to a ldif formatted blob
      43             : 
      44             :   If mask_errors is true, then function succeeds but out data
      45             :   is set to "<Unable to decode binary data>" message
      46             : 
      47             :   \return 0 on success; -1 on error
      48             : */
      49       16585 : static int ldif_write_NDR(struct ldb_context *ldb, void *mem_ctx,
      50             :                           const struct ldb_val *in, struct ldb_val *out,
      51             :                           size_t struct_size,
      52             :                           ndr_pull_flags_fn_t pull_fn,
      53             :                           ndr_print_fn_t print_fn,
      54             :                           bool mask_errors)
      55             : {
      56       15603 :         uint8_t *p;
      57       15603 :         enum ndr_err_code err;
      58       16585 :         if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
      59       16573 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
      60             :         }
      61          12 :         p = talloc_size(mem_ctx, struct_size);
      62          12 :         err = ndr_pull_struct_blob(in, mem_ctx,
      63             :                                    p, pull_fn);
      64          12 :         if (err != NDR_ERR_SUCCESS) {
      65             :                 /* fail in not in mask_error mode */
      66           0 :                 if (!mask_errors) {
      67           0 :                         return -1;
      68             :                 }
      69           0 :                 talloc_free(p);
      70           0 :                 out->data = (uint8_t *)talloc_strdup(mem_ctx, "<Unable to decode binary data>");
      71           0 :                 out->length = strlen((const char *)out->data);
      72           0 :                 return 0;
      73             :         }
      74          12 :         out->data = (uint8_t *)ndr_print_struct_string(mem_ctx, print_fn, "NDR", p);
      75          12 :         talloc_free(p);
      76          12 :         if (out->data == NULL) {
      77           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
      78             :         }
      79          12 :         out->length = strlen((char *)out->data);
      80          12 :         return 0;
      81             : }
      82             : 
      83             : /*
      84             :   convert a ldif formatted objectSid to a NDR formatted blob
      85             : */
      86    23961876 : static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
      87             :                                const struct ldb_val *in, struct ldb_val *out)
      88             : {
      89      613700 :         bool ret;
      90      613700 :         enum ndr_err_code ndr_err;
      91      613700 :         struct dom_sid sid;
      92    23961876 :         if (in->length > DOM_SID_STR_BUFLEN) {
      93           0 :                 return -1;
      94             :         }
      95    23961876 :         if (in->length < 5) { /* "S-1-x" */
      96         282 :                 return -1;
      97             :         }
      98    23961594 :         if (in->data[0] != 'S' && in->data[0] != 's') {
      99    11468133 :                 return -1;
     100             :         } else {
     101      252719 :                 char p[DOM_SID_STR_BUFLEN + 1];
     102    12132480 :                 memcpy(p, in->data, in->length);
     103    12132480 :                 p[in->length] = '\0';
     104             : 
     105    12132480 :                 ret = dom_sid_parse(p, &sid);
     106    12132480 :                 if (ret == false) {
     107         136 :                         return -1;
     108             :                 }
     109             : 
     110    12132344 :                 *out = data_blob_talloc(mem_ctx, NULL,
     111             :                                         ndr_size_dom_sid(&sid, 0));
     112    12132344 :                 if (out->data == NULL) {
     113           0 :                         return -1;
     114             :                 }
     115             : 
     116    12132344 :                 ndr_err = ndr_push_struct_into_fixed_blob(out, &sid,
     117             :                                 (ndr_push_flags_fn_t)ndr_push_dom_sid);
     118    12132344 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     119           0 :                         TALLOC_FREE(out->data);
     120           0 :                         return -1;
     121             :                 }
     122             :         }
     123    12132344 :         return 0;
     124             : }
     125             : 
     126             : /*
     127             :   convert a NDR formatted blob to a ldif formatted objectSid
     128             : */
     129     7819127 : int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
     130             :                                 const struct ldb_val *in, struct ldb_val *out)
     131             : {
     132      114505 :         struct dom_sid sid;
     133      114505 :         enum ndr_err_code ndr_err;
     134             : 
     135     7819127 :         ndr_err = ndr_pull_struct_blob_all_noalloc(in, &sid,
     136             :                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
     137     7819127 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     138           0 :                 return -1;
     139             :         }
     140     7819127 :         *out = data_blob_string_const(dom_sid_string(mem_ctx, &sid));
     141     7819127 :         if (out->data == NULL) {
     142           0 :                 return -1;
     143             :         }
     144     7704622 :         return 0;
     145             : }
     146             : 
     147             : /*
     148             :   compare two objectSids
     149             : 
     150             :   If the SIDs seem to be strings, they are converted to binary form.
     151             : */
     152     2088686 : static int ldif_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
     153             :                                     const struct ldb_val *v1, const struct ldb_val *v2)
     154             : {
     155     2088686 :         struct ldb_val parsed_1 = {.data = NULL};
     156     2088686 :         struct ldb_val parsed_2 = {.data = NULL};
     157       47085 :         int ret;
     158             :         /*
     159             :          * If the ldb_vals look like SID strings (i.e. start with "S-"
     160             :          * or "s-"), we treat them as strings.
     161             :          *
     162             :          * It is not really possible for a blob to be both a SID string and a
     163             :          * SID struct -- the first two bytes of a struct dom_sid (including in
     164             :          * NDR form) are the version (1), and the number of sub-auths (<= 15),
     165             :          * neither of which are close to 'S' or '-'.
     166             :          */
     167     2088686 :         ret = ldif_read_objectSid(ldb, mem_ctx, v1, &parsed_1);
     168     2088686 :         if (ret == 0) {
     169      122564 :                 v1 = &parsed_1;
     170             :         }
     171     2088686 :         ret = ldif_read_objectSid(ldb, mem_ctx, v2, &parsed_2);
     172     2088686 :         if (ret == 0) {
     173           2 :                 v2 = &parsed_2;
     174             :         }
     175             : 
     176     2088686 :         ret = ldb_comparison_binary(ldb, mem_ctx, v1, v2);
     177             : 
     178     2088686 :         TALLOC_FREE(parsed_1.data);
     179     2088686 :         TALLOC_FREE(parsed_2.data);
     180     2088686 :         return ret;
     181             : }
     182             : 
     183             : /*
     184             :   canonicalise a objectSid
     185             : */
     186     8046808 : static int ldif_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
     187             :                                       const struct ldb_val *in, struct ldb_val *out)
     188             : {
     189             :         /* First try as a string SID */
     190     8046808 :         if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
     191      276083 :                 return 0;
     192             :         }
     193             :         /* not a string after all */
     194     7762991 :         return ldb_handler_copy(ldb, mem_ctx, in, out);
     195             : }
     196             : 
     197    11726500 : static int extended_dn_read_SID(struct ldb_context *ldb, void *mem_ctx,
     198             :                               const struct ldb_val *in, struct ldb_val *out)
     199             : {
     200      240691 :         struct dom_sid sid;
     201      240691 :         enum ndr_err_code ndr_err;
     202             : 
     203    11726500 :         if (ldif_read_objectSid(ldb, mem_ctx, in, out) == 0) {
     204    11474212 :                 return 0;
     205             :         }
     206             : 
     207             :         /* Perhaps not a string after all */
     208       11734 :         *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
     209             : 
     210       11734 :         if (!out->data) {
     211           0 :                 return -1;
     212             :         }
     213             : 
     214       23468 :         (*out).length = strhex_to_str((char *)out->data, out->length,
     215       11734 :                                      (const char *)in->data, in->length);
     216             : 
     217             :         /* Check it looks like a SID */
     218       11734 :         ndr_err = ndr_pull_struct_blob_all_noalloc(out, &sid,
     219             :                                            (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
     220       11734 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     221         429 :                 TALLOC_FREE(out->data);
     222         429 :                 return -1;
     223             :         }
     224       11171 :         return 0;
     225             : }
     226             : 
     227             : /*
     228             :   convert a ldif formatted objectGUID to a NDR formatted blob
     229             : */
     230    96181178 : static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     231             :                                 const struct ldb_val *in, struct ldb_val *out)
     232             : {
     233     1330330 :         struct GUID guid;
     234     1330330 :         NTSTATUS status;
     235             : 
     236    96181178 :         status = GUID_from_data_blob(in, &guid);
     237    96181178 :         if (!NT_STATUS_IS_OK(status)) {
     238           0 :                 return -1;
     239             :         }
     240             : 
     241    96181178 :         status = GUID_to_ndr_blob(&guid, mem_ctx, out);
     242    96181178 :         if (!NT_STATUS_IS_OK(status)) {
     243           0 :                 return -1;
     244             :         }
     245    94850848 :         return 0;
     246             : }
     247             : 
     248             : /*
     249             :   convert a NDR formatted blob to a ldif formatted objectGUID
     250             : */
     251    16528904 : static int ldif_write_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     252             :                                  const struct ldb_val *in, struct ldb_val *out)
     253             : {
     254      221730 :         struct GUID guid;
     255      221730 :         NTSTATUS status;
     256             : 
     257    16528904 :         status = GUID_from_ndr_blob(in, &guid);
     258    16528904 :         if (!NT_STATUS_IS_OK(status)) {
     259           0 :                 return -1;
     260             :         }
     261    16528904 :         out->data = (uint8_t *)GUID_string(mem_ctx, &guid);
     262    16528904 :         if (out->data == NULL) {
     263           0 :                 return -1;
     264             :         }
     265    16528904 :         out->length = strlen((const char *)out->data);
     266    16528904 :         return 0;
     267             : }
     268             : 
     269   165680067 : static bool ldif_comparision_objectGUID_isString(const struct ldb_val *v)
     270             : {
     271   167344246 :         if (v->length != 36 && v->length != 38) return false;
     272             : 
     273             :         /* Might be a GUID string, can't be a binary GUID (fixed 16 bytes) */
     274    73999751 :         return true;
     275             : }
     276             : 
     277    32082895 : static int extended_dn_read_GUID(struct ldb_context *ldb, void *mem_ctx,
     278             :                               const struct ldb_val *in, struct ldb_val *out)
     279             : {
     280             : 
     281    32082895 :         if (in->length == 36 && ldif_read_objectGUID(ldb, mem_ctx, in, out) == 0) {
     282    30926012 :                 return 0;
     283             :         }
     284             : 
     285             :         /* Try as 'hex' form */
     286      418373 :         if (in->length != 32) {
     287           0 :                 return -1;
     288             :         }
     289             : 
     290      418368 :         *out = data_blob_talloc(mem_ctx, NULL, in->length/2+1);
     291             : 
     292      418368 :         if (!out->data) {
     293           0 :                 return -1;
     294             :         }
     295             : 
     296      836736 :         (*out).length = strhex_to_str((char *)out->data, out->length,
     297      418368 :                                       (const char *)in->data, in->length);
     298             : 
     299             :         /* Check it looks like a GUID */
     300      418368 :         if ((*out).length != 16) {
     301           0 :                 data_blob_free(out);
     302           0 :                 return -1;
     303             :         }
     304             : 
     305      417588 :         return 0;
     306             : }
     307             : 
     308             : /*
     309             :   compare two objectGUIDs
     310             : */
     311    19775653 : static int ldif_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     312             :                                      const struct ldb_val *v1, const struct ldb_val *v2)
     313             : {
     314    19775653 :         if (ldif_comparision_objectGUID_isString(v1) && ldif_comparision_objectGUID_isString(v2)) {
     315           1 :                 return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
     316    19775652 :         } else if (ldif_comparision_objectGUID_isString(v1)
     317    12212864 :                    && !ldif_comparision_objectGUID_isString(v2)) {
     318       76642 :                 struct ldb_val v;
     319       76642 :                 int ret;
     320    11868376 :                 if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
     321             :                         /* Perhaps it wasn't a valid string after all */
     322           0 :                         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
     323             :                 }
     324    11868376 :                 ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
     325    11868376 :                 talloc_free(v.data);
     326    11868376 :                 return ret;
     327     7907276 :         } else if (!ldif_comparision_objectGUID_isString(v1)
     328     7907276 :                    && ldif_comparision_objectGUID_isString(v2)) {
     329           1 :                 struct ldb_val v;
     330           1 :                 int ret;
     331           1 :                 if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
     332             :                         /* Perhaps it wasn't a valid string after all */
     333           0 :                         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
     334             :                 }
     335           1 :                 ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
     336           1 :                 talloc_free(v.data);
     337           1 :                 return ret;
     338             :         }
     339     7907275 :         return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
     340             : }
     341             : 
     342             : /*
     343             :   canonicalise a objectGUID
     344             : */
     345    86577457 : static int ldif_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
     346             :                                        const struct ldb_val *in, struct ldb_val *out)
     347             : {
     348    86577457 :         if (ldif_comparision_objectGUID_isString(in)) {
     349    50757862 :                 if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
     350             :                         /* Perhaps it wasn't a valid string after all */
     351           0 :                         return ldb_handler_copy(ldb, mem_ctx, in, out);
     352             :                 }
     353    50416283 :                 return 0;
     354             :         }
     355    35819595 :         return ldb_handler_copy(ldb, mem_ctx, in, out);
     356             : }
     357             : 
     358             : 
     359             : /*
     360             :   convert a ldif (SDDL) formatted ntSecurityDescriptor to a NDR formatted blob
     361             : */
     362        7956 : static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
     363             :                                           const struct ldb_val *in, struct ldb_val *out)
     364             : {
     365        1646 :         struct security_descriptor *sd;
     366        1646 :         enum ndr_err_code ndr_err;
     367             : 
     368        7956 :         if (in->length >= 2 && isupper(in->data[0]) && in->data[1] == ':') {
     369             :                 /*
     370             :                  * If it starts with an upper case character followed by ':',
     371             :                  * we know it's not NDR, but most likely SDDL...
     372             :                  */
     373        4103 :                 const struct dom_sid *sid = samdb_domain_sid(ldb);
     374             : 
     375        4103 :                 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
     376        4103 :                 if (sd == NULL) {
     377           0 :                         return -1;
     378             :                 }
     379             : 
     380        4103 :                 goto decoded;
     381             :         }
     382             : 
     383        3853 :         sd = talloc(mem_ctx, struct security_descriptor);
     384        3853 :         if (sd == NULL) {
     385           0 :                 return -1;
     386             :         }
     387             : 
     388        3853 :         ndr_err = ndr_pull_struct_blob(in, sd, sd,
     389             :                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     390        3853 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     391           0 :                 talloc_free(sd);
     392           0 :                 return -1;
     393             :         }
     394             : 
     395        3853 : decoded:
     396        7956 :         ndr_err = ndr_push_struct_blob(out, mem_ctx, sd,
     397             :                                        (ndr_push_flags_fn_t)ndr_push_security_descriptor);
     398        7956 :         talloc_free(sd);
     399        7956 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     400           0 :                 return -1;
     401             :         }
     402             : 
     403        6310 :         return 0;
     404             : }
     405             : 
     406             : /*
     407             :   convert a NDR formatted blob to a ldif formatted ntSecurityDescriptor (SDDL format)
     408             : */
     409       15148 : static int ldif_write_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
     410             :                                            const struct ldb_val *in, struct ldb_val *out)
     411             : {
     412       15148 :         struct security_descriptor *sd;
     413       15148 :         enum ndr_err_code ndr_err;
     414             : 
     415       15148 :         if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
     416           0 :                 return ldif_write_NDR(ldb, mem_ctx, in, out,
     417             :                                       sizeof(struct security_descriptor),
     418             :                                       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor,
     419             :                                       (ndr_print_fn_t)ndr_print_security_descriptor,
     420             :                                       true);
     421             : 
     422             :         }
     423             : 
     424       15148 :         sd = talloc(mem_ctx, struct security_descriptor);
     425       15148 :         if (sd == NULL) {
     426           0 :                 return -1;
     427             :         }
     428             :         /* We can't use ndr_pull_struct_blob_all because this contains relative pointers */
     429       15148 :         ndr_err = ndr_pull_struct_blob(in, sd, sd,
     430             :                                            (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     431       15148 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     432           0 :                 talloc_free(sd);
     433           0 :                 return -1;
     434             :         }
     435       15148 :         out->data = (uint8_t *)sddl_encode(mem_ctx, sd, samdb_domain_sid_cache_only(ldb));
     436       15148 :         talloc_free(sd);
     437       15148 :         if (out->data == NULL) {
     438           0 :                 return -1;
     439             :         }
     440       15148 :         out->length = strlen((const char *)out->data);
     441       15148 :         return 0;
     442             : }
     443             : 
     444             : /*
     445             :   convert a string formatted SDDL to a ldif formatted ntSecurityDescriptor (SDDL format)
     446             : */
     447        1772 : static int ldif_write_sddlSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx,
     448             :                                            const struct ldb_val *in, struct ldb_val *out)
     449             : {
     450        1772 :         if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
     451           0 :                 struct security_descriptor *sd;
     452           0 :                 const struct dom_sid *sid = samdb_domain_sid(ldb);
     453             : 
     454           0 :                 sd = sddl_decode(mem_ctx, (const char *)in->data, sid);
     455           0 :                 out->data = (uint8_t *)ndr_print_struct_string(mem_ctx,
     456             :                                         (ndr_print_fn_t)ndr_print_security_descriptor,
     457             :                                         "SDDL", sd);
     458           0 :                 out->length = strlen((const char *)out->data);
     459           0 :                 talloc_free(sd);
     460           0 :                 return 0;
     461             :         }
     462             : 
     463        1772 :         return ldb_handler_copy(ldb, mem_ctx, in, out);
     464             : }
     465             : 
     466             : /*
     467             :    canonicalise an objectCategory.  We use the long form as the canonical form:
     468             :    'person' becomes cn=Person,cn=Schema,cn=Configuration,<basedn>
     469             : 
     470             :    Also any short name of an objectClass that points to a different
     471             :    class (such as user) has the canonical form of the class it's
     472             :    defaultObjectCategory points to (eg
     473             :    cn=Person,cn=Schema,cn=Configuration,<basedn>)
     474             : */
     475             : 
     476     2328976 : static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_ctx,
     477             :                                             const struct ldb_val *in, struct ldb_val *out)
     478             : {
     479     2328976 :         struct ldb_dn *dn1 = NULL;
     480     2328976 :         const struct dsdb_schema *schema = dsdb_get_schema(ldb, NULL);
     481      202390 :         const struct dsdb_class *sclass;
     482     2328976 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     483     2328976 :         if (!tmp_ctx) {
     484           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     485             :         }
     486             : 
     487     2328976 :         if (!schema) {
     488           2 :                 talloc_free(tmp_ctx);
     489           2 :                 *out = data_blob_talloc(mem_ctx, in->data, in->length);
     490           2 :                 if (in->data && !out->data) {
     491           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     492             :                 }
     493           2 :                 return LDB_SUCCESS;
     494             :         }
     495     2328974 :         dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
     496     2328974 :         if ( ! ldb_dn_validate(dn1)) {
     497       11691 :                 const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
     498       11691 :                 sclass = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
     499       11691 :                 if (sclass) {
     500       11695 :                         struct ldb_dn *dn = ldb_dn_new(tmp_ctx, ldb,
     501       11691 :                                                        sclass->defaultObjectCategory);
     502       11691 :                         if (dn == NULL) {
     503           0 :                                 talloc_free(tmp_ctx);
     504           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
     505             :                         }
     506             : 
     507       11691 :                         *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn));
     508       11691 :                         talloc_free(tmp_ctx);
     509             : 
     510       11691 :                         if (!out->data) {
     511           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
     512             :                         }
     513       11691 :                         return LDB_SUCCESS;
     514             :                 } else {
     515           0 :                         *out = data_blob_talloc(mem_ctx, in->data, in->length);
     516           0 :                         talloc_free(tmp_ctx);
     517             : 
     518           0 :                         if (in->data && !out->data) {
     519           0 :                                 return LDB_ERR_OPERATIONS_ERROR;
     520             :                         }
     521           0 :                         return LDB_SUCCESS;
     522             :                 }
     523             :         }
     524     2317283 :         *out = data_blob_string_const(ldb_dn_alloc_casefold(mem_ctx, dn1));
     525     2317283 :         talloc_free(tmp_ctx);
     526             : 
     527     2317283 :         if (!out->data) {
     528           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     529             :         }
     530     2114897 :         return LDB_SUCCESS;
     531             : }
     532             : 
     533       77758 : static int ldif_comparison_objectCategory(struct ldb_context *ldb, void *mem_ctx,
     534             :                                           const struct ldb_val *v1,
     535             :                                           const struct ldb_val *v2)
     536             : {
     537       77758 :         return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_objectCategory,
     538             :                                   v1, v2);
     539             : }
     540             : 
     541             : /*
     542             :   convert a NDR formatted blob to a ldif formatted schemaInfo
     543             : */
     544          17 : static int ldif_write_schemaInfo(struct ldb_context *ldb, void *mem_ctx,
     545             :                                  const struct ldb_val *in, struct ldb_val *out)
     546             : {
     547          17 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
     548             :                               sizeof(struct schemaInfoBlob),
     549             :                               (ndr_pull_flags_fn_t)ndr_pull_schemaInfoBlob,
     550             :                               (ndr_print_fn_t)ndr_print_schemaInfoBlob,
     551             :                               true);
     552             : }
     553             : 
     554             : /*
     555             :   convert a ldif formatted prefixMap to a NDR formatted blob
     556             : */
     557         398 : static int ldif_read_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     558             :                                const struct ldb_val *in, struct ldb_val *out)
     559             : {
     560          29 :         struct prefixMapBlob *blob;
     561          29 :         enum ndr_err_code ndr_err;
     562          29 :         char *string, *line, *p, *oid;
     563          29 :         DATA_BLOB oid_blob;
     564             : 
     565         398 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     566             : 
     567         398 :         if (tmp_ctx == NULL) {
     568           0 :                 return -1;
     569             :         }
     570             : 
     571         398 :         blob = talloc_zero(tmp_ctx, struct prefixMapBlob);
     572         398 :         if (blob == NULL) {
     573           0 :                 talloc_free(tmp_ctx);
     574           0 :                 return -1;
     575             :         }
     576             : 
     577             :         /* use the switch value to detect if this is in the binary
     578             :          * format
     579             :          */
     580         398 :         if (in->length >= 4 && IVAL(in->data, 0) == PREFIX_MAP_VERSION_DSDB) {
     581          76 :                 ndr_err = ndr_pull_struct_blob(in, tmp_ctx, blob,
     582             :                                                (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
     583          76 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     584          76 :                         ndr_err = ndr_push_struct_blob(out, mem_ctx,
     585             :                                                        blob,
     586             :                                                        (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
     587          76 :                         talloc_free(tmp_ctx);
     588          76 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     589           0 :                                 return -1;
     590             :                         }
     591          76 :                         return 0;
     592             :                 }
     593             :         }
     594             : 
     595             :         /* If this does not parse, then it is probably the text version, and we should try it that way */
     596         322 :         blob->version = PREFIX_MAP_VERSION_DSDB;
     597             : 
     598         322 :         string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
     599         322 :         if (string == NULL) {
     600           0 :                 talloc_free(blob);
     601           0 :                 return -1;
     602             :         }
     603             : 
     604         293 :         line = string;
     605       13329 :         while (line && line[0]) {
     606       13007 :                 int error = 0;
     607             : 
     608       13007 :                 p=strchr(line, ';');
     609       13007 :                 if (p) {
     610         122 :                         p[0] = '\0';
     611             :                 } else {
     612       12885 :                         p=strchr(line, '\n');
     613       12885 :                         if (p) {
     614       12877 :                                 p[0] = '\0';
     615             :                         }
     616             :                 }
     617             :                 /* allow a trailing separator */
     618       13007 :                 if (line == p) {
     619           0 :                         break;
     620             :                 }
     621             : 
     622       13007 :                 blob->ctr.dsdb.mappings = talloc_realloc(blob,
     623             :                                                          blob->ctr.dsdb.mappings,
     624             :                                                          struct drsuapi_DsReplicaOIDMapping,
     625             :                                                          blob->ctr.dsdb.num_mappings+1);
     626       13007 :                 if (!blob->ctr.dsdb.mappings) {
     627           0 :                         talloc_free(tmp_ctx);
     628           0 :                         return -1;
     629             :                 }
     630             : 
     631       14001 :                 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].id_prefix =
     632       13007 :                         smb_strtoul(line, &oid, 10, &error, SMB_STR_STANDARD);
     633             : 
     634       13007 :                 if (oid[0] != ':' || error != 0) {
     635           0 :                         talloc_free(tmp_ctx);
     636           0 :                         return -1;
     637             :                 }
     638             : 
     639             :                 /* we know there must be at least ":" */
     640       13007 :                 oid++;
     641             : 
     642       13007 :                 if (!ber_write_partial_OID_String(blob->ctr.dsdb.mappings, &oid_blob, oid)) {
     643           0 :                         talloc_free(tmp_ctx);
     644           0 :                         return -1;
     645             :                 }
     646       13007 :                 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.length = oid_blob.length;
     647       13007 :                 blob->ctr.dsdb.mappings[blob->ctr.dsdb.num_mappings].oid.binary_oid = oid_blob.data;
     648             : 
     649       13007 :                 blob->ctr.dsdb.num_mappings++;
     650             : 
     651             :                 /* Now look past the terminator we added above */
     652       13007 :                 if (p) {
     653       12999 :                         line = p + 1;
     654             :                 } else {
     655           3 :                         line = NULL;
     656             :                 }
     657             :         }
     658             : 
     659         322 :         ndr_err = ndr_push_struct_blob(out, mem_ctx,
     660             :                                        blob,
     661             :                                        (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
     662         322 :         talloc_free(tmp_ctx);
     663         322 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     664           0 :                 return -1;
     665             :         }
     666         293 :         return 0;
     667             : }
     668             : 
     669             : /*
     670             :   convert a NDR formatted blob to a ldif formatted prefixMap
     671             : */
     672           8 : static int ldif_write_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     673             :                                 const struct ldb_val *in, struct ldb_val *out)
     674             : {
     675           5 :         struct prefixMapBlob *blob;
     676           5 :         enum ndr_err_code ndr_err;
     677           5 :         char *string;
     678           5 :         uint32_t i;
     679             : 
     680           8 :         if (ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY) {
     681           0 :                 int err;
     682             :                 /* try to decode the blob as S4 prefixMap */
     683           0 :                 err = ldif_write_NDR(ldb, mem_ctx, in, out,
     684             :                                      sizeof(struct prefixMapBlob),
     685             :                                      (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob,
     686             :                                      (ndr_print_fn_t)ndr_print_prefixMapBlob,
     687             :                                      false);
     688           0 :                 if (0 == err) {
     689           0 :                         return err;
     690             :                 }
     691             :                 /* try parsing it as Windows PrefixMap value */
     692           0 :                 return ldif_write_NDR(ldb, mem_ctx, in, out,
     693             :                                       sizeof(struct drsuapi_MSPrefixMap_Ctr),
     694             :                                       (ndr_pull_flags_fn_t)ndr_pull_drsuapi_MSPrefixMap_Ctr,
     695             :                                       (ndr_print_fn_t)ndr_print_drsuapi_MSPrefixMap_Ctr,
     696             :                                       true);
     697             :         }
     698             : 
     699           8 :         blob = talloc(mem_ctx, struct prefixMapBlob);
     700           8 :         if (blob == NULL) {
     701           0 :                 return -1;
     702             :         }
     703           8 :         ndr_err = ndr_pull_struct_blob_all(in, blob,
     704             :                                            blob,
     705             :                                            (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
     706           8 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     707           0 :                 goto failed;
     708             :         }
     709           8 :         if (blob->version != PREFIX_MAP_VERSION_DSDB) {
     710           0 :                 goto failed;
     711             :         }
     712           8 :         string = talloc_strdup(mem_ctx, "");
     713           8 :         if (string == NULL) {
     714           0 :                 goto failed;
     715             :         }
     716             : 
     717         297 :         for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
     718         166 :                 DATA_BLOB oid_blob;
     719         289 :                 char *partial_oid = NULL;
     720             : 
     721         289 :                 if (i > 0) {
     722         281 :                         talloc_asprintf_addbuf(&string, ";");
     723             :                 }
     724             : 
     725         289 :                 oid_blob = data_blob_const(blob->ctr.dsdb.mappings[i].oid.binary_oid,
     726         289 :                                            blob->ctr.dsdb.mappings[i].oid.length);
     727         289 :                 if (!ber_read_partial_OID_String(blob, oid_blob, &partial_oid)) {
     728           0 :                         DEBUG(0, ("ber_read_partial_OID failed on prefixMap item with id: 0x%X\n",
     729             :                                   blob->ctr.dsdb.mappings[i].id_prefix));
     730           0 :                         goto failed;
     731             :                 }
     732         289 :                 talloc_asprintf_addbuf(&string, "%u:%s",
     733         289 :                                        blob->ctr.dsdb.mappings[i].id_prefix,
     734             :                                        partial_oid);
     735         289 :                 talloc_free(discard_const(partial_oid));
     736             :         }
     737             : 
     738           8 :         talloc_free(blob);
     739           8 :         *out = data_blob_string_const(string);
     740           8 :         return 0;
     741             : 
     742           0 : failed:
     743           0 :         talloc_free(blob);
     744           0 :         return -1;
     745             : }
     746             : 
     747           6 : static bool ldif_comparision_prefixMap_isString(const struct ldb_val *v)
     748             : {
     749           6 :         if (v->length < 4) {
     750           0 :                 return true;
     751             :         }
     752             : 
     753           6 :         if (IVAL(v->data, 0) == PREFIX_MAP_VERSION_DSDB) {
     754           2 :                 return false;
     755             :         }
     756             : 
     757           0 :         return true;
     758             : }
     759             : 
     760             : /*
     761             :   canonicalise a prefixMap
     762             : */
     763           6 : static int ldif_canonicalise_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     764             :                                        const struct ldb_val *in, struct ldb_val *out)
     765             : {
     766           6 :         if (ldif_comparision_prefixMap_isString(in)) {
     767           4 :                 return ldif_read_prefixMap(ldb, mem_ctx, in, out);
     768             :         }
     769           2 :         return ldb_handler_copy(ldb, mem_ctx, in, out);
     770             : }
     771             : 
     772           3 : static int ldif_comparison_prefixMap(struct ldb_context *ldb, void *mem_ctx,
     773             :                                      const struct ldb_val *v1,
     774             :                                      const struct ldb_val *v2)
     775             : {
     776           3 :         return ldb_any_comparison(ldb, mem_ctx, ldif_canonicalise_prefixMap,
     777             :                                   v1, v2);
     778             : }
     779             : 
     780             : /* length limited conversion of a ldb_val to a int32_t */
     781     3094949 : static int val_to_int32(const struct ldb_val *in, int32_t *v)
     782             : {
     783      250288 :         char *end;
     784      250288 :         char buf[64];
     785             : 
     786             :         /* make sure we don't read past the end of the data */
     787     3094949 :         if (in->length > sizeof(buf)-1) {
     788           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     789             :         }
     790     3094949 :         strncpy(buf, (char *)in->data, in->length);
     791     3094949 :         buf[in->length] = 0;
     792             : 
     793             :         /* We've to use "strtoll" here to have the intended overflows.
     794             :          * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
     795     3094949 :         *v = (int32_t) strtoll(buf, &end, 0);
     796     3094949 :         if (*end != 0) {
     797          66 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     798             :         }
     799     2844595 :         return LDB_SUCCESS;
     800             : }
     801             : 
     802             : /* length limited conversion of a ldb_val to a int64_t */
     803        1920 : static int val_to_int64(const struct ldb_val *in, int64_t *v)
     804             : {
     805         154 :         char *end;
     806         154 :         char buf[64];
     807             : 
     808             :         /* make sure we don't read past the end of the data */
     809        1920 :         if (in->length > sizeof(buf)-1) {
     810           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     811             :         }
     812        1920 :         strncpy(buf, (char *)in->data, in->length);
     813        1920 :         buf[in->length] = 0;
     814             : 
     815        1920 :         *v = (int64_t) strtoll(buf, &end, 0);
     816        1920 :         if (*end != 0) {
     817          72 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
     818             :         }
     819        1766 :         return LDB_SUCCESS;
     820             : }
     821             : 
     822             : /* Canonicalisation of two 32-bit integers */
     823     1741926 : static int ldif_canonicalise_int32(struct ldb_context *ldb, void *mem_ctx,
     824             :                         const struct ldb_val *in, struct ldb_val *out)
     825             : {
     826      233798 :         int32_t i;
     827      233798 :         int ret;
     828             : 
     829     1741926 :         ret = val_to_int32(in, &i);
     830     1741926 :         if (ret != LDB_SUCCESS) {
     831           6 :                 return ret;
     832             :         }
     833     1741920 :         out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%d", i);
     834     1741920 :         if (out->data == NULL) {
     835           0 :                 ldb_oom(ldb);
     836           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     837             :         }
     838     1741920 :         out->length = strlen((char *)out->data);
     839     1741920 :         return 0;
     840             : }
     841             : 
     842             : /*
     843             :  * Lexicographically sorted representation for a 32-bit integer
     844             :  *
     845             :  * [ INT32_MIN ... -3, -2, -1 | 0 | +1, +2, +3 ... INT32_MAX ]
     846             :  *             n                o              p
     847             :  *
     848             :  * Refer to the comment in lib/ldb/common/attrib_handlers.c for the
     849             :  * corresponding documentation for 64-bit integers.
     850             :  *
     851             :  * The same rules apply but use INT32_MIN and INT32_MAX.
     852             :  *
     853             :  * String representation padding is done to 10 characters.
     854             :  *
     855             :  * INT32_MAX = 2^31 - 1 = 2147483647 (10 characters long)
     856             :  *
     857             :  */
     858      635937 : static int ldif_index_format_int32(struct ldb_context *ldb,
     859             :                                     void *mem_ctx,
     860             :                                     const struct ldb_val *in,
     861             :                                     struct ldb_val *out)
     862             : {
     863        6528 :         int32_t i;
     864        6528 :         int ret;
     865        6528 :         char prefix;
     866        6528 :         size_t len;
     867             : 
     868      635937 :         ret = val_to_int32(in, &i);
     869      635937 :         if (ret != LDB_SUCCESS) {
     870           0 :                 return ret;
     871             :         }
     872             : 
     873      635937 :         if (i < 0) {
     874             :                 /*
     875             :                  * i is negative, so this is subtraction rather than
     876             :                  * wrap-around.
     877             :                  */
     878       51820 :                 prefix = 'n';
     879       51820 :                 i = INT32_MAX + i + 1;
     880      584117 :         } else if (i > 0) {
     881      579684 :                 prefix = 'p';
     882             :         } else {
     883          30 :                 prefix = 'o';
     884             :         }
     885             : 
     886      635937 :         out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%c%010ld", prefix, (long)i);
     887      635937 :         if (out->data == NULL) {
     888           0 :                 ldb_oom(ldb);
     889           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     890             :         }
     891             : 
     892      635937 :         len = talloc_array_length(out->data) - 1;
     893      635937 :         if (len != 11) {
     894           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     895             :                           __location__ ": expected index format str %s to"
     896             :                           " have length 11 but got %zu",
     897           0 :                           (char*)out->data, len);
     898           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     899             :         }
     900             : 
     901      635937 :         out->length = 11;
     902      635937 :         return 0;
     903             : }
     904             : 
     905             : /* Comparison of two 32-bit integers */
     906      358543 : static int ldif_comparison_int32(struct ldb_context *ldb, void *mem_ctx,
     907             :                                  const struct ldb_val *v1, const struct ldb_val *v2)
     908             : {
     909      358543 :         int32_t i1=0, i2=0;
     910      358543 :         val_to_int32(v1, &i1);
     911      358543 :         val_to_int32(v2, &i2);
     912      358543 :         if (i1 == i2) return 0;
     913      228864 :         return i1 > i2? 1 : -1;
     914             : }
     915             : 
     916             : /* Canonicalisation of two 64-bit integers */
     917        1102 : static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
     918             :                                    const struct ldb_val *in, struct ldb_val *out)
     919             : {
     920          66 :         int64_t i;
     921          66 :         int ret;
     922             : 
     923        1102 :         ret = val_to_int64(in, &i);
     924        1102 :         if (ret != LDB_SUCCESS) {
     925           0 :                 return ret;
     926             :         }
     927        1102 :         out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
     928        1102 :         if (out->data == NULL) {
     929           0 :                 ldb_oom(ldb);
     930           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     931             :         }
     932        1102 :         out->length = strlen((char *)out->data);
     933        1102 :         return 0;
     934             : }
     935             : 
     936             : /* Comparison of two 64-bit integers */
     937         279 : static int ldif_comparison_int64(struct ldb_context *ldb, void *mem_ctx,
     938             :                                  const struct ldb_val *v1, const struct ldb_val *v2)
     939             : {
     940         279 :         int64_t i1=0, i2=0;
     941         279 :         val_to_int64(v1, &i1);
     942         279 :         val_to_int64(v2, &i2);
     943         279 :         if (i1 == i2) return 0;
     944           0 :         return i1 > i2? 1 : -1;
     945             : }
     946             : 
     947             : /*
     948             :   convert a NDR formatted blob to a ldif formatted repsFromTo
     949             : */
     950           4 : static int ldif_write_repsFromTo(struct ldb_context *ldb, void *mem_ctx,
     951             :                                  const struct ldb_val *in, struct ldb_val *out)
     952             : {
     953           4 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
     954             :                               sizeof(struct repsFromToBlob),
     955             :                               (ndr_pull_flags_fn_t)ndr_pull_repsFromToBlob,
     956             :                               (ndr_print_fn_t)ndr_print_repsFromToBlob,
     957             :                               true);
     958             : }
     959             : 
     960             : /*
     961             :   convert a NDR formatted blob to a ldif formatted replPropertyMetaData
     962             : */
     963       15160 : static int ldif_write_replPropertyMetaData(struct ldb_context *ldb, void *mem_ctx,
     964             :                                            const struct ldb_val *in, struct ldb_val *out)
     965             : {
     966       15160 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
     967             :                               sizeof(struct replPropertyMetaDataBlob),
     968             :                               (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob,
     969             :                               (ndr_print_fn_t)ndr_print_replPropertyMetaDataBlob,
     970             :                               true);
     971             : }
     972             : 
     973             : /*
     974             :   convert a NDR formatted blob to a ldif formatted replUpToDateVector
     975             : */
     976           1 : static int ldif_write_replUpToDateVector(struct ldb_context *ldb, void *mem_ctx,
     977             :                                          const struct ldb_val *in, struct ldb_val *out)
     978             : {
     979           1 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
     980             :                               sizeof(struct replUpToDateVectorBlob),
     981             :                               (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob,
     982             :                               (ndr_print_fn_t)ndr_print_replUpToDateVectorBlob,
     983             :                               true);
     984             : }
     985             : 
     986           0 : static int ldif_write_dn_binary_NDR(struct ldb_context *ldb, void *mem_ctx,
     987             :                                     const struct ldb_val *in, struct ldb_val *out,
     988             :                                     size_t struct_size,
     989             :                                     ndr_pull_flags_fn_t pull_fn,
     990             :                                     ndr_print_fn_t print_fn,
     991             :                                     bool mask_errors)
     992             : {
     993           0 :         uint8_t *p = NULL;
     994           0 :         enum ndr_err_code err;
     995           0 :         struct dsdb_dn *dsdb_dn = NULL;
     996           0 :         char *dn_str = NULL;
     997           0 :         char *str = NULL;
     998             : 
     999           0 :         if (!(ldb_get_flags(ldb) & LDB_FLG_SHOW_BINARY)) {
    1000           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
    1001             :         }
    1002             : 
    1003           0 :         dsdb_dn = dsdb_dn_parse(mem_ctx, ldb, in, DSDB_SYNTAX_BINARY_DN);
    1004           0 :         if (dsdb_dn == NULL) {
    1005           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
    1006             :         }
    1007             : 
    1008           0 :         p = talloc_size(dsdb_dn, struct_size);
    1009           0 :         if (p == NULL) {
    1010           0 :                 TALLOC_FREE(dsdb_dn);
    1011           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
    1012             :         }
    1013             : 
    1014           0 :         err = ndr_pull_struct_blob(&dsdb_dn->extra_part, p, p, pull_fn);
    1015           0 :         if (err != NDR_ERR_SUCCESS) {
    1016             :                 /* fail in not in mask_error mode */
    1017           0 :                 if (!mask_errors) {
    1018           0 :                         return -1;
    1019             :                 }
    1020           0 :                 TALLOC_FREE(dsdb_dn);
    1021           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
    1022             :         }
    1023             : 
    1024           0 :         dn_str = ldb_dn_get_extended_linearized(dsdb_dn, dsdb_dn->dn, 1);
    1025           0 :         if (dn_str == NULL) {
    1026           0 :                 TALLOC_FREE(dsdb_dn);
    1027           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
    1028             :         }
    1029             : 
    1030           0 :         str = ndr_print_struct_string(mem_ctx, print_fn, dn_str, p);
    1031           0 :         TALLOC_FREE(dsdb_dn);
    1032           0 :         if (str == NULL) {
    1033           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
    1034             :         }
    1035             : 
    1036           0 :         *out = data_blob_string_const(str);
    1037           0 :         return 0;
    1038             : }
    1039             : 
    1040           0 : static int ldif_write_msDS_RevealedUsers(struct ldb_context *ldb, void *mem_ctx,
    1041             :                                          const struct ldb_val *in, struct ldb_val *out)
    1042             : {
    1043           0 :         return ldif_write_dn_binary_NDR(ldb, mem_ctx, in, out,
    1044             :                               sizeof(struct replPropertyMetaData1),
    1045             :                               (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaData1,
    1046             :                               (ndr_print_fn_t)ndr_print_replPropertyMetaData1,
    1047             :                               true);
    1048             : }
    1049             : 
    1050             : /*
    1051             :   convert a NDR formatted blob to a ldif formatted dnsRecord
    1052             : */
    1053         928 : static int ldif_write_dnsRecord(struct ldb_context *ldb, void *mem_ctx,
    1054             :                                 const struct ldb_val *in, struct ldb_val *out)
    1055             : {
    1056         928 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
    1057             :                               sizeof(struct dnsp_DnssrvRpcRecord),
    1058             :                               (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord,
    1059             :                               (ndr_print_fn_t)ndr_print_dnsp_DnssrvRpcRecord,
    1060             :                               true);
    1061             : }
    1062             : 
    1063             : /*
    1064             :   convert a NDR formatted blob to a ldif formatted dnsProperty
    1065             : */
    1066         238 : static int ldif_write_dnsProperty(struct ldb_context *ldb, void *mem_ctx,
    1067             :                                 const struct ldb_val *in, struct ldb_val *out)
    1068             : {
    1069         238 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
    1070             :                               sizeof(struct dnsp_DnsProperty),
    1071             :                               (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnsProperty,
    1072             :                               (ndr_print_fn_t)ndr_print_dnsp_DnsProperty,
    1073             :                               true);
    1074             : }
    1075             : 
    1076             : /*
    1077             :   convert a NDR formatted blob of a supplementalCredentials into text
    1078             : */
    1079         237 : static int ldif_write_supplementalCredentialsBlob(struct ldb_context *ldb, void *mem_ctx,
    1080             :                                                   const struct ldb_val *in, struct ldb_val *out)
    1081             : {
    1082         237 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
    1083             :                               sizeof(struct supplementalCredentialsBlob),
    1084             :                               (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob,
    1085             :                               (ndr_print_fn_t)ndr_print_supplementalCredentialsBlob,
    1086             :                               true);
    1087             : }
    1088             : 
    1089             : /*
    1090             :   convert a NDR formatted blob to a ldif formatted trustAuthInOutBlob
    1091             : */
    1092           0 : static int ldif_write_trustAuthInOutBlob(struct ldb_context *ldb, void *mem_ctx,
    1093             :                                            const struct ldb_val *in, struct ldb_val *out)
    1094             : {
    1095           0 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
    1096             :                               sizeof(struct trustAuthInOutBlob),
    1097             :                               (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob,
    1098             :                               (ndr_print_fn_t)ndr_print_trustAuthInOutBlob,
    1099             :                               true);
    1100             : }
    1101             : 
    1102             : /*
    1103             :   convert a NDR formatted blob to a ldif formatted msDS-TrustForestTrustInfo
    1104             : */
    1105           0 : static int ldif_write_ForestTrustInfo(struct ldb_context *ldb, void *mem_ctx,
    1106             :                                       const struct ldb_val *in, struct ldb_val *out)
    1107             : {
    1108           0 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
    1109             :                               sizeof(struct ForestTrustInfo),
    1110             :                               (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo,
    1111             :                               (ndr_print_fn_t)ndr_print_ForestTrustInfo,
    1112             :                               true);
    1113             : }
    1114             : /*
    1115             :   convert a NDR formatted blob of a partialAttributeSet into text
    1116             : */
    1117           0 : static int ldif_write_partialAttributeSet(struct ldb_context *ldb, void *mem_ctx,
    1118             :                                           const struct ldb_val *in, struct ldb_val *out)
    1119             : {
    1120           0 :         return ldif_write_NDR(ldb, mem_ctx, in, out,
    1121             :                               sizeof(struct partialAttributeSetBlob),
    1122             :                               (ndr_pull_flags_fn_t)ndr_pull_partialAttributeSetBlob,
    1123             :                               (ndr_print_fn_t)ndr_print_partialAttributeSetBlob,
    1124             :                               true);
    1125             : }
    1126             : 
    1127             : 
    1128     8051272 : static int extended_dn_write_hex(struct ldb_context *ldb, void *mem_ctx,
    1129             :                                  const struct ldb_val *in, struct ldb_val *out)
    1130             : {
    1131     8051272 :         *out = data_blob_string_const(data_blob_hex_string_lower(mem_ctx, in));
    1132     8051272 :         if (!out->data) {
    1133           0 :                 return -1;
    1134             :         }
    1135     7832847 :         return 0;
    1136             : }
    1137             : 
    1138             : /*
    1139             :   compare two dns
    1140             : */
    1141           0 : static int samba_ldb_dn_link_comparison(struct ldb_context *ldb, void *mem_ctx,
    1142             :                                         const struct ldb_val *v1, const struct ldb_val *v2)
    1143             : {
    1144           0 :         struct ldb_dn *dn1 = NULL, *dn2 = NULL;
    1145           0 :         int ret;
    1146             : 
    1147             :         /*
    1148             :          * In a sort context, Deleted DNs get shifted to the end.
    1149             :          * They never match in an equality
    1150             :          */
    1151           0 :         if (dsdb_dn_is_deleted_val(v1)) {
    1152           0 :                 if (! dsdb_dn_is_deleted_val(v2)) {
    1153           0 :                         return 1;
    1154             :                 }
    1155             :                 /*
    1156             :                  * They are both deleted!
    1157             :                  *
    1158             :                  * The soundest thing to do at this point is carry on
    1159             :                  * and compare the DNs normally. This matches the
    1160             :                  * behaviour of samba_dn_extended_match() below.
    1161             :                  */
    1162           0 :         } else if (dsdb_dn_is_deleted_val(v2)) {
    1163           0 :                 return -1;
    1164             :         }
    1165             : 
    1166           0 :         dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
    1167           0 :         dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
    1168             : 
    1169           0 :         if ( ! ldb_dn_validate(dn1)) {
    1170           0 :                 TALLOC_FREE(dn1);
    1171           0 :                 if ( ! ldb_dn_validate(dn2)) {
    1172           0 :                         TALLOC_FREE(dn2);
    1173           0 :                         return 0;
    1174             :                 }
    1175           0 :                 TALLOC_FREE(dn2);
    1176           0 :                 return 1;
    1177             :         }
    1178             : 
    1179           0 :         if ( ! ldb_dn_validate(dn2)) {
    1180           0 :                 TALLOC_FREE(dn1);
    1181           0 :                 TALLOC_FREE(dn2);
    1182           0 :                 return -1;
    1183             :         }
    1184             : 
    1185           0 :         ret = ldb_dn_compare(dn1, dn2);
    1186             : 
    1187           0 :         talloc_free(dn1);
    1188           0 :         talloc_free(dn2);
    1189           0 :         return ret;
    1190             : }
    1191             : 
    1192       27085 : static int samba_ldb_dn_link_canonicalise(struct ldb_context *ldb, void *mem_ctx,
    1193             :                                           const struct ldb_val *in, struct ldb_val *out)
    1194             : {
    1195         699 :         struct ldb_dn *dn;
    1196       27085 :         int ret = -1;
    1197             : 
    1198       27085 :         out->length = 0;
    1199       27085 :         out->data = NULL;
    1200             : 
    1201       27085 :         dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
    1202       27085 :         if ( ! ldb_dn_validate(dn)) {
    1203           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
    1204             :         }
    1205             : 
    1206             :         /* By including the RMD_FLAGS of a deleted DN, we ensure it
    1207             :          * does not casually match a not deleted DN */
    1208       27085 :         if (dsdb_dn_is_deleted_val(in)) {
    1209           0 :                 out->data = (uint8_t *)talloc_asprintf(mem_ctx,
    1210             :                                                        "<RMD_FLAGS=%u>%s",
    1211             :                                                        dsdb_dn_val_rmd_flags(in),
    1212             :                                                        ldb_dn_get_casefold(dn));
    1213             :         } else {
    1214       27085 :                 out->data = (uint8_t *)ldb_dn_alloc_casefold(mem_ctx, dn);
    1215             :         }
    1216             : 
    1217       27085 :         if (out->data == NULL) {
    1218           0 :                 goto done;
    1219             :         }
    1220       27085 :         out->length = strlen((char *)out->data);
    1221             : 
    1222       27085 :         ret = 0;
    1223             : 
    1224       27085 : done:
    1225       27085 :         talloc_free(dn);
    1226             : 
    1227       27085 :         return ret;
    1228             : }
    1229             : 
    1230             : 
    1231             : /*
    1232             :   write a 64 bit 2-part range
    1233             : */
    1234         260 : static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
    1235             :                               const struct ldb_val *in, struct ldb_val *out)
    1236             : {
    1237          88 :         int64_t v;
    1238          88 :         int ret;
    1239         260 :         ret = val_to_int64(in, &v);
    1240         260 :         if (ret != LDB_SUCCESS) {
    1241           0 :                 return ret;
    1242             :         }
    1243         376 :         out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
    1244         188 :                                                (unsigned long)(v&0xFFFFFFFF),
    1245         188 :                                                (unsigned long)(v>>32));
    1246         188 :         if (out->data == NULL) {
    1247           0 :                 ldb_oom(ldb);
    1248           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1249             :         }
    1250         188 :         out->length = strlen((char *)out->data);
    1251         188 :         return LDB_SUCCESS;
    1252             : }
    1253             : 
    1254             : /*
    1255             :   read a 64 bit 2-part range
    1256             : */
    1257         382 : static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
    1258             :                               const struct ldb_val *in, struct ldb_val *out)
    1259             : {
    1260          66 :         unsigned long high, low;
    1261          66 :         char buf[64];
    1262             : 
    1263         382 :         if (memchr(in->data, '-', in->length) == NULL) {
    1264           0 :                 return ldb_handler_copy(ldb, mem_ctx, in, out);
    1265             :         }
    1266             : 
    1267         382 :         if (in->length > sizeof(buf)-1) {
    1268           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1269             :         }
    1270         382 :         strncpy(buf, (const char *)in->data, in->length);
    1271         382 :         buf[in->length] = 0;
    1272             : 
    1273         382 :         if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
    1274           0 :                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
    1275             :         }
    1276             : 
    1277         764 :         out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
    1278         382 :                                                (unsigned long long)(((uint64_t)high)<<32) | (low));
    1279             : 
    1280         382 :         if (out->data == NULL) {
    1281           0 :                 ldb_oom(ldb);
    1282           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1283             :         }
    1284         382 :         out->length = strlen((char *)out->data);
    1285         382 :         return LDB_SUCCESS;
    1286             : }
    1287             : 
    1288             : /*
    1289             :   when this operator_fn is set for a syntax, the backend calls is in
    1290             :   preference to the comparison function. We are told the exact
    1291             :   comparison operation that is needed, and we can return errors
    1292             :  */
    1293    21362579 : static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
    1294             :                                     const struct ldb_schema_attribute *a,
    1295             :                                     const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
    1296             : {
    1297    21362579 :         switch (operation) {
    1298           0 :         case LDB_OP_AND:
    1299             :         case LDB_OP_OR:
    1300             :         case LDB_OP_NOT:
    1301             :         case LDB_OP_SUBSTRING:
    1302             :         case LDB_OP_APPROX:
    1303             :         case LDB_OP_EXTENDED:
    1304             :                 /* handled in the backends */
    1305           0 :                 return LDB_ERR_INAPPROPRIATE_MATCHING;
    1306             : 
    1307    21135879 :         case LDB_OP_GREATER:
    1308             :         case LDB_OP_LESS:
    1309             :         case LDB_OP_EQUALITY:
    1310             :         {
    1311    21135879 :                 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
    1312      475010 :                 int ret;
    1313    21135879 :                 if (tmp_ctx == NULL) {
    1314           0 :                         return ldb_oom(ldb);
    1315             :                 }
    1316    21135879 :                 ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
    1317    21135879 :                 talloc_free(tmp_ctx);
    1318    21135879 :                 if (operation == LDB_OP_GREATER) {
    1319         982 :                         *matched = (ret >= 0);
    1320    21134897 :                 } else if (operation == LDB_OP_LESS) {
    1321         862 :                         *matched = (ret <= 0);
    1322             :                 } else {
    1323    21134035 :                         *matched = (ret == 0);
    1324             :                 }
    1325    20660869 :                 return LDB_SUCCESS;
    1326             :         }
    1327             : 
    1328      226700 :         case LDB_OP_PRESENT:
    1329      226700 :                 *matched = true;
    1330      226700 :                 return LDB_SUCCESS;
    1331             :         }
    1332             : 
    1333             :         /* we shouldn't get here */
    1334           0 :         return LDB_ERR_INAPPROPRIATE_MATCHING;
    1335             : }
    1336             : 
    1337             : /*
    1338             :   compare two binary objects.  This is correct for sorting as the sort order is:
    1339             : 
    1340             :   a
    1341             :   aa
    1342             :   b
    1343             :   bb
    1344             : 
    1345             :   rather than ldb_comparison_binary() which is:
    1346             : 
    1347             :   a
    1348             :   b
    1349             :   aa
    1350             :   bb
    1351             : 
    1352             : */
    1353       62008 : static int samba_ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
    1354             :                                        const struct ldb_val *v1, const struct ldb_val *v2)
    1355             : {
    1356       62008 :         return data_blob_cmp(v1, v2);
    1357             : }
    1358             : 
    1359             : /*
    1360             :   when this operator_fn is set for a syntax, the backend calls is in
    1361             :   preference to the comparison function. We are told the exact
    1362             :   comparison operation that is needed, and we can return errors.
    1363             : 
    1364             :   This mode optimises for ldb_comparison_binary() if we need equality,
    1365             :   as this should be faster as it can do a length-check first.
    1366             :  */
    1367          31 : static int samba_syntax_binary_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
    1368             :                                            const struct ldb_schema_attribute *a,
    1369             :                                            const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
    1370             : {
    1371          31 :         if (operation == LDB_OP_EQUALITY) {
    1372          25 :                 *matched = (ldb_comparison_binary(ldb, NULL, v1, v2) == 0);
    1373          25 :                 return LDB_SUCCESS;
    1374             :         }
    1375           6 :         return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
    1376             : }
    1377             : 
    1378             : /*
    1379             :   see if two DNs match, comparing first by GUID, then by SID, and
    1380             :   finally by string components
    1381             :  */
    1382      347139 : static int samba_dn_extended_match(struct ldb_context *ldb,
    1383             :                                    const struct ldb_val *v1,
    1384             :                                    const struct ldb_val *v2,
    1385             :                                    bool *matched)
    1386             : {
    1387        9626 :         TALLOC_CTX *tmp_ctx;
    1388        9626 :         struct ldb_dn *dn1, *dn2;
    1389        9626 :         const struct ldb_val *guid1, *guid2, *sid1, *sid2;
    1390        9626 :         uint32_t rmd_flags1, rmd_flags2;
    1391             : 
    1392      347139 :         tmp_ctx = talloc_new(ldb);
    1393             : 
    1394      347139 :         dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v1);
    1395      347139 :         dn2 = ldb_dn_from_ldb_val(tmp_ctx, ldb, v2);
    1396      347139 :         if (!dn1 || !dn2) {
    1397             :                 /* couldn't parse as DN's */
    1398           0 :                 talloc_free(tmp_ctx);
    1399           0 :                 (*matched) = false;
    1400           0 :                 return LDB_SUCCESS;
    1401             :         }
    1402             : 
    1403      347139 :         rmd_flags1 = dsdb_dn_rmd_flags(dn1);
    1404      347139 :         rmd_flags2 = dsdb_dn_rmd_flags(dn2);
    1405             : 
    1406      347139 :         if ((rmd_flags1 & DSDB_RMD_FLAG_DELETED) !=
    1407             :             (rmd_flags2 & DSDB_RMD_FLAG_DELETED)) {
    1408             :                 /* only match if they have the same deletion status */
    1409        1107 :                 talloc_free(tmp_ctx);
    1410        1107 :                 (*matched) = false;
    1411        1107 :                 return LDB_SUCCESS;
    1412             :         }
    1413             : 
    1414             : 
    1415      346032 :         guid1 = ldb_dn_get_extended_component(dn1, "GUID");
    1416      346032 :         guid2 = ldb_dn_get_extended_component(dn2, "GUID");
    1417      346032 :         if (guid1 && guid2) {
    1418      283156 :                 (*matched) = (data_blob_cmp(guid1, guid2) == 0);
    1419      283156 :                 talloc_free(tmp_ctx);
    1420      283156 :                 return LDB_SUCCESS;
    1421             :         }
    1422             : 
    1423       62876 :         sid1 = ldb_dn_get_extended_component(dn1, "SID");
    1424       62876 :         sid2 = ldb_dn_get_extended_component(dn2, "SID");
    1425       62876 :         if (sid1 && sid2) {
    1426       11802 :                 (*matched) = (data_blob_cmp(sid1, sid2) == 0);
    1427       11802 :                 talloc_free(tmp_ctx);
    1428       11802 :                 return LDB_SUCCESS;
    1429             :         }
    1430             : 
    1431       51074 :         (*matched) = (ldb_dn_compare(dn1, dn2) == 0);
    1432             : 
    1433       51074 :         talloc_free(tmp_ctx);
    1434       51074 :         return LDB_SUCCESS;
    1435             : }
    1436             : 
    1437             : /*
    1438             :   special operation for DNs, to take account of the RMD_FLAGS deleted bit
    1439             :  */
    1440      347680 : static int samba_syntax_operator_dn(struct ldb_context *ldb, enum ldb_parse_op operation,
    1441             :                                     const struct ldb_schema_attribute *a,
    1442             :                                     const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
    1443             : {
    1444      347680 :         if (operation == LDB_OP_PRESENT && dsdb_dn_is_deleted_val(v1)) {
    1445             :                 /* If the DN is deleted, then we can't search for it */
    1446             : 
    1447             :                 /* should this be for equality too? */
    1448           0 :                 *matched = false;
    1449           0 :                 return LDB_SUCCESS;
    1450             :         }
    1451             : 
    1452      694819 :         if (operation == LDB_OP_EQUALITY &&
    1453      347139 :             samba_dn_extended_match(ldb, v1, v2, matched) == LDB_SUCCESS) {
    1454      337513 :                 return LDB_SUCCESS;
    1455             :         }
    1456             : 
    1457         541 :         return samba_syntax_operator_fn(ldb, operation, a, v1, v2, matched);
    1458             : }
    1459             : 
    1460             : 
    1461             : static const struct ldb_schema_syntax samba_syntaxes[] = {
    1462             :         {
    1463             :                 .name             = LDB_SYNTAX_SAMBA_SID,
    1464             :                 .ldif_read_fn     = ldif_read_objectSid,
    1465             :                 .ldif_write_fn    = ldif_write_objectSid,
    1466             :                 .canonicalise_fn  = ldif_canonicalise_objectSid,
    1467             :                 .comparison_fn    = ldif_comparison_objectSid,
    1468             :                 .operator_fn      = samba_syntax_operator_fn
    1469             :         },{
    1470             :                 .name             = LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
    1471             :                 .ldif_read_fn     = ldif_read_ntSecurityDescriptor,
    1472             :                 .ldif_write_fn    = ldif_write_ntSecurityDescriptor,
    1473             :                 .canonicalise_fn  = ldb_handler_copy,
    1474             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1475             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1476             :         },{
    1477             :                 .name             = LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR,
    1478             :                 .ldif_read_fn     = ldb_handler_copy,
    1479             :                 .ldif_write_fn    = ldif_write_sddlSecurityDescriptor,
    1480             :                 .canonicalise_fn  = ldb_handler_fold,
    1481             :                 .comparison_fn    = ldb_comparison_fold,
    1482             :                 .operator_fn      = samba_syntax_operator_fn
    1483             :         },{
    1484             :                 .name             = LDB_SYNTAX_SAMBA_GUID,
    1485             :                 .ldif_read_fn     = ldif_read_objectGUID,
    1486             :                 .ldif_write_fn    = ldif_write_objectGUID,
    1487             :                 .canonicalise_fn  = ldif_canonicalise_objectGUID,
    1488             :                 .comparison_fn    = ldif_comparison_objectGUID,
    1489             :                 .operator_fn      = samba_syntax_operator_fn
    1490             :         },{
    1491             :                 .name             = LDB_SYNTAX_SAMBA_OBJECT_CATEGORY,
    1492             :                 .ldif_read_fn     = ldb_handler_copy,
    1493             :                 .ldif_write_fn    = ldb_handler_copy,
    1494             :                 .canonicalise_fn  = ldif_canonicalise_objectCategory,
    1495             :                 .comparison_fn    = ldif_comparison_objectCategory,
    1496             :                 .operator_fn      = samba_syntax_operator_fn
    1497             :         },{
    1498             :                 .name             = LDB_SYNTAX_SAMBA_SCHEMAINFO,
    1499             :                 .ldif_read_fn     = ldb_handler_copy,
    1500             :                 .ldif_write_fn    = ldif_write_schemaInfo,
    1501             :                 .canonicalise_fn  = ldb_handler_copy,
    1502             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1503             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1504             :         },{
    1505             :                 .name             = LDB_SYNTAX_SAMBA_PREFIX_MAP,
    1506             :                 .ldif_read_fn     = ldif_read_prefixMap,
    1507             :                 .ldif_write_fn    = ldif_write_prefixMap,
    1508             :                 .canonicalise_fn  = ldif_canonicalise_prefixMap,
    1509             :                 .comparison_fn    = ldif_comparison_prefixMap,
    1510             :                 .operator_fn      = samba_syntax_operator_fn
    1511             :         },{
    1512             :                 .name             = LDB_SYNTAX_SAMBA_INT32,
    1513             :                 .ldif_read_fn     = ldb_handler_copy,
    1514             :                 .ldif_write_fn    = ldb_handler_copy,
    1515             :                 .canonicalise_fn  = ldif_canonicalise_int32,
    1516             :                 .index_format_fn  = ldif_index_format_int32,
    1517             :                 .comparison_fn    = ldif_comparison_int32,
    1518             :                 .operator_fn      = samba_syntax_operator_fn
    1519             :         },{
    1520             :                 .name             = LDB_SYNTAX_SAMBA_REPSFROMTO,
    1521             :                 .ldif_read_fn     = ldb_handler_copy,
    1522             :                 .ldif_write_fn    = ldif_write_repsFromTo,
    1523             :                 .canonicalise_fn  = ldb_handler_copy,
    1524             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1525             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1526             :         },{
    1527             :                 .name             = LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA,
    1528             :                 .ldif_read_fn     = ldb_handler_copy,
    1529             :                 .ldif_write_fn    = ldif_write_replPropertyMetaData,
    1530             :                 .canonicalise_fn  = ldb_handler_copy,
    1531             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1532             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1533             :         },{
    1534             :                 .name             = LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR,
    1535             :                 .ldif_read_fn     = ldb_handler_copy,
    1536             :                 .ldif_write_fn    = ldif_write_replUpToDateVector,
    1537             :                 .canonicalise_fn  = ldb_handler_copy,
    1538             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1539             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1540             :         },{
    1541             :                 .name             = LDB_SYNTAX_SAMBA_REVEALEDUSERS,
    1542             :                 .ldif_read_fn     = ldb_handler_copy,
    1543             :                 .ldif_write_fn    = ldif_write_msDS_RevealedUsers,
    1544             :                 .canonicalise_fn  = dsdb_dn_binary_canonicalise,
    1545             :                 .comparison_fn    = dsdb_dn_binary_comparison,
    1546             :                 .operator_fn      = samba_syntax_operator_fn
    1547             :         },{
    1548             :                 .name             = LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB,
    1549             :                 .ldif_read_fn     = ldb_handler_copy,
    1550             :                 .ldif_write_fn    = ldif_write_trustAuthInOutBlob,
    1551             :                 .canonicalise_fn  = ldb_handler_copy,
    1552             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1553             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1554             :         },{
    1555             :                 .name             = LDB_SYNTAX_SAMBA_FORESTTRUSTINFO,
    1556             :                 .ldif_read_fn     = ldb_handler_copy,
    1557             :                 .ldif_write_fn    = ldif_write_ForestTrustInfo,
    1558             :                 .canonicalise_fn  = ldb_handler_copy,
    1559             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1560             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1561             :         },{
    1562             :                 .name             = DSDB_SYNTAX_BINARY_DN,
    1563             :                 .ldif_read_fn     = ldb_handler_copy,
    1564             :                 .ldif_write_fn    = ldb_handler_copy,
    1565             :                 .canonicalise_fn  = dsdb_dn_binary_canonicalise,
    1566             :                 .comparison_fn    = dsdb_dn_binary_comparison,
    1567             :                 .operator_fn      = samba_syntax_operator_fn
    1568             :         },{
    1569             :                 .name             = DSDB_SYNTAX_STRING_DN,
    1570             :                 .ldif_read_fn     = ldb_handler_copy,
    1571             :                 .ldif_write_fn    = ldb_handler_copy,
    1572             :                 .canonicalise_fn  = dsdb_dn_string_canonicalise,
    1573             :                 .comparison_fn    = dsdb_dn_string_comparison,
    1574             :                 .operator_fn      = samba_syntax_operator_fn
    1575             :         },{
    1576             :                 .name             = LDB_SYNTAX_DN,
    1577             :                 .ldif_read_fn     = ldb_handler_copy,
    1578             :                 .ldif_write_fn    = ldb_handler_copy,
    1579             :                 .canonicalise_fn  = samba_ldb_dn_link_canonicalise,
    1580             :                 .comparison_fn    = samba_ldb_dn_link_comparison,
    1581             :                 .operator_fn      = samba_syntax_operator_dn
    1582             :         },{
    1583             :                 .name             = LDB_SYNTAX_SAMBA_RANGE64,
    1584             :                 .ldif_read_fn     = ldif_read_range64,
    1585             :                 .ldif_write_fn    = ldif_write_range64,
    1586             :                 .canonicalise_fn  = ldif_canonicalise_int64,
    1587             :                 .comparison_fn    = ldif_comparison_int64,
    1588             :                 .operator_fn      = samba_syntax_operator_fn
    1589             :         },{
    1590             :                 .name             = LDB_SYNTAX_SAMBA_DNSRECORD,
    1591             :                 .ldif_read_fn     = ldb_handler_copy,
    1592             :                 .ldif_write_fn    = ldif_write_dnsRecord,
    1593             :                 .canonicalise_fn  = ldb_handler_copy,
    1594             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1595             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1596             :         },{
    1597             :                 .name             = LDB_SYNTAX_SAMBA_DNSPROPERTY,
    1598             :                 .ldif_read_fn     = ldb_handler_copy,
    1599             :                 .ldif_write_fn    = ldif_write_dnsProperty,
    1600             :                 .canonicalise_fn  = ldb_handler_copy,
    1601             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1602             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1603             :         },{
    1604             :                 .name             = LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS,
    1605             :                 .ldif_read_fn     = ldb_handler_copy,
    1606             :                 .ldif_write_fn    = ldif_write_supplementalCredentialsBlob,
    1607             :                 .canonicalise_fn  = ldb_handler_copy,
    1608             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1609             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1610             :         },{
    1611             :                 .name             = LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET,
    1612             :                 .ldif_read_fn     = ldb_handler_copy,
    1613             :                 .ldif_write_fn    = ldif_write_partialAttributeSet,
    1614             :                 .canonicalise_fn  = ldb_handler_copy,
    1615             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1616             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1617             :         },{
    1618             :                 .name             = LDB_SYNTAX_SAMBA_OCTET_STRING,
    1619             :                 .ldif_read_fn     = ldb_handler_copy,
    1620             :                 .ldif_write_fn    = ldb_handler_copy,
    1621             :                 .canonicalise_fn  = ldb_handler_copy,
    1622             :                 .comparison_fn    = samba_ldb_comparison_binary,
    1623             :                 .operator_fn      = samba_syntax_binary_operator_fn
    1624             :         }
    1625             : };
    1626             : 
    1627             : static const struct ldb_dn_extended_syntax samba_dn_syntax[] = {
    1628             :         {
    1629             :                 .name             = "SID",
    1630             :                 .read_fn          = extended_dn_read_SID,
    1631             :                 .write_clear_fn   = ldif_write_objectSid,
    1632             :                 .write_hex_fn     = extended_dn_write_hex
    1633             :         },{
    1634             :                 .name             = "GUID",
    1635             :                 .read_fn          = extended_dn_read_GUID,
    1636             :                 .write_clear_fn   = ldif_write_objectGUID,
    1637             :                 .write_hex_fn     = extended_dn_write_hex
    1638             :         },{
    1639             :                 .name             = "WKGUID",
    1640             :                 .read_fn          = ldb_handler_copy,
    1641             :                 .write_clear_fn   = ldb_handler_copy,
    1642             :                 .write_hex_fn     = ldb_handler_copy
    1643             :         },{
    1644             :                 .name             = "RMD_INVOCID",
    1645             :                 .read_fn          = extended_dn_read_GUID,
    1646             :                 .write_clear_fn   = ldif_write_objectGUID,
    1647             :                 .write_hex_fn     = extended_dn_write_hex
    1648             :         },{
    1649             :                 .name             = "RMD_FLAGS",
    1650             :                 .read_fn          = ldb_handler_copy,
    1651             :                 .write_clear_fn   = ldb_handler_copy,
    1652             :                 .write_hex_fn     = ldb_handler_copy
    1653             :         },{
    1654             :                 .name             = "RMD_ADDTIME",
    1655             :                 .read_fn          = ldb_handler_copy,
    1656             :                 .write_clear_fn   = ldb_handler_copy,
    1657             :                 .write_hex_fn     = ldb_handler_copy
    1658             :         },{
    1659             :                 .name             = "RMD_CHANGETIME",
    1660             :                 .read_fn          = ldb_handler_copy,
    1661             :                 .write_clear_fn   = ldb_handler_copy,
    1662             :                 .write_hex_fn     = ldb_handler_copy
    1663             :         },{
    1664             :                 .name             = "RMD_LOCAL_USN",
    1665             :                 .read_fn          = ldb_handler_copy,
    1666             :                 .write_clear_fn   = ldb_handler_copy,
    1667             :                 .write_hex_fn     = ldb_handler_copy
    1668             :         },{
    1669             :                 .name             = "RMD_ORIGINATING_USN",
    1670             :                 .read_fn          = ldb_handler_copy,
    1671             :                 .write_clear_fn   = ldb_handler_copy,
    1672             :                 .write_hex_fn     = ldb_handler_copy
    1673             :         },{
    1674             :                 .name             = "RMD_VERSION",
    1675             :                 .read_fn          = ldb_handler_copy,
    1676             :                 .write_clear_fn   = ldb_handler_copy,
    1677             :                 .write_hex_fn     = ldb_handler_copy
    1678             :         }
    1679             : };
    1680             : 
    1681             : /* TODO: Should be dynamic at some point */
    1682             : static const struct {
    1683             :         const char *name;
    1684             :         const char *syntax;
    1685             : } samba_attributes[] = {
    1686             :         { "ntSecurityDescriptor",     LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR },
    1687             :         { "oMSyntax",                 LDB_SYNTAX_SAMBA_INT32 },
    1688             :         { "objectCategory",           LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
    1689             :         { "schemaInfo",                       LDB_SYNTAX_SAMBA_SCHEMAINFO },
    1690             :         { "prefixMap",                  LDB_SYNTAX_SAMBA_PREFIX_MAP },
    1691             :         { "repsFrom",                   LDB_SYNTAX_SAMBA_REPSFROMTO },
    1692             :         { "repsTo",                     LDB_SYNTAX_SAMBA_REPSFROMTO },
    1693             :         { "replPropertyMetaData",       LDB_SYNTAX_SAMBA_REPLPROPERTYMETADATA },
    1694             :         { "replUpToDateVector",         LDB_SYNTAX_SAMBA_REPLUPTODATEVECTOR },
    1695             :         { "msDS-RevealedUsers",         LDB_SYNTAX_SAMBA_REVEALEDUSERS },
    1696             :         { "trustAuthIncoming",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
    1697             :         { "trustAuthOutgoing",          LDB_SYNTAX_SAMBA_TRUSTAUTHINOUTBLOB },
    1698             :         { "msDS-TrustForestTrustInfo",  LDB_SYNTAX_SAMBA_FORESTTRUSTINFO },
    1699             :         { "rIDAllocationPool",                LDB_SYNTAX_SAMBA_RANGE64 },
    1700             :         { "rIDPreviousAllocationPool",        LDB_SYNTAX_SAMBA_RANGE64 },
    1701             :         { "rIDAvailablePool",         LDB_SYNTAX_SAMBA_RANGE64 },
    1702             :         { "defaultSecurityDescriptor",        LDB_SYNTAX_SAMBA_SDDL_SECURITY_DESCRIPTOR },
    1703             : 
    1704             :         /*
    1705             :          * these are extracted by searching
    1706             :          * (&(attributeSyntax=2.5.5.17)(omSyntax=4))
    1707             :          *
    1708             :          * Except: msAuthz-CentralAccessPolicyID as it might be a GUID see:
    1709             :          * adminDescription: For a Central Access Policy, this attribute defines a GUID t
    1710             :          * hat can be used to identify the set of policies when applied to a resource.
    1711             :          * Until we see a msAuthz-CentralAccessPolicyID value on a windows
    1712             :          * server, we ignore it here.
    1713             :          */
    1714             :         { "mS-DS-CreatorSID",         LDB_SYNTAX_SAMBA_SID },
    1715             :         { "msDS-QuotaTrustee",                LDB_SYNTAX_SAMBA_SID },
    1716             :         { "objectSid",                        LDB_SYNTAX_SAMBA_SID },
    1717             :         { "tokenGroups",              LDB_SYNTAX_SAMBA_SID },
    1718             :         { "tokenGroupsGlobalAndUniversal", LDB_SYNTAX_SAMBA_SID },
    1719             :         { "tokenGroupsNoGCAcceptable",  LDB_SYNTAX_SAMBA_SID },
    1720             :         { "securityIdentifier",       LDB_SYNTAX_SAMBA_SID },
    1721             :         { "sIDHistory",                       LDB_SYNTAX_SAMBA_SID },
    1722             :         { "syncWithSID",              LDB_SYNTAX_SAMBA_SID },
    1723             : 
    1724             :         /*
    1725             :          * these are extracted by searching
    1726             :          * (&(attributeSyntax=2.5.5.10)(rangeLower=16)(rangeUpper=16)(omSyntax=4))
    1727             :          */
    1728             :         { "attributeSecurityGUID",            LDB_SYNTAX_SAMBA_GUID },
    1729             :         { "categoryId",                               LDB_SYNTAX_SAMBA_GUID },
    1730             :         { "controlAccessRights",              LDB_SYNTAX_SAMBA_GUID },
    1731             :         { "currMachineId",                    LDB_SYNTAX_SAMBA_GUID },
    1732             :         { "fRSReplicaSetGUID",                        LDB_SYNTAX_SAMBA_GUID },
    1733             :         { "fRSVersionGUID",                   LDB_SYNTAX_SAMBA_GUID },
    1734             :         { "implementedCategories",            LDB_SYNTAX_SAMBA_GUID },
    1735             :         { "msDS-AzObjectGuid",                        LDB_SYNTAX_SAMBA_GUID },
    1736             :         { "msDS-GenerationId",                        LDB_SYNTAX_SAMBA_GUID },
    1737             :         { "msDS-OptionalFeatureGUID",         LDB_SYNTAX_SAMBA_GUID },
    1738             :         { "msDFSR-ContentSetGuid",            LDB_SYNTAX_SAMBA_GUID },
    1739             :         { "msDFSR-ReplicationGroupGuid",      LDB_SYNTAX_SAMBA_GUID },
    1740             :         { "mSMQDigests",                      LDB_SYNTAX_SAMBA_GUID },
    1741             :         { "mSMQOwnerID",                      LDB_SYNTAX_SAMBA_GUID },
    1742             :         { "mSMQQMID",                         LDB_SYNTAX_SAMBA_GUID },
    1743             :         { "mSMQQueueType",                    LDB_SYNTAX_SAMBA_GUID },
    1744             :         { "mSMQSites",                                LDB_SYNTAX_SAMBA_GUID },
    1745             :         { "netbootGUID",                      LDB_SYNTAX_SAMBA_GUID },
    1746             :         { "objectGUID",                               LDB_SYNTAX_SAMBA_GUID },
    1747             :         { "pKTGuid",                          LDB_SYNTAX_SAMBA_GUID },
    1748             :         { "requiredCategories",                       LDB_SYNTAX_SAMBA_GUID },
    1749             :         { "schemaIDGUID",                     LDB_SYNTAX_SAMBA_GUID },
    1750             :         { "siteGUID",                         LDB_SYNTAX_SAMBA_GUID },
    1751             :         { "msDFS-GenerationGUIDv2",           LDB_SYNTAX_SAMBA_GUID },
    1752             :         { "msDFS-LinkIdentityGUIDv2",         LDB_SYNTAX_SAMBA_GUID },
    1753             :         { "msDFS-NamespaceIdentityGUIDv2",    LDB_SYNTAX_SAMBA_GUID },
    1754             :         { "msSPP-CSVLKSkuId",                 LDB_SYNTAX_SAMBA_GUID },
    1755             :         { "msSPP-KMSIds",                     LDB_SYNTAX_SAMBA_GUID },
    1756             : 
    1757             :         /*
    1758             :          * these are known to be GUIDs
    1759             :          */
    1760             :         { "invocationId",                     LDB_SYNTAX_SAMBA_GUID },
    1761             :         { "parentGUID",                               LDB_SYNTAX_SAMBA_GUID },
    1762             : 
    1763             :         /* These NDR encoded things we want to be able to read with --show-binary */
    1764             :         { "dnsRecord",                                LDB_SYNTAX_SAMBA_DNSRECORD },
    1765             :         { "dNSProperty",                      LDB_SYNTAX_SAMBA_DNSPROPERTY },
    1766             :         { "supplementalCredentials",          LDB_SYNTAX_SAMBA_SUPPLEMENTALCREDENTIALS},
    1767             :         { "partialAttributeSet",              LDB_SYNTAX_SAMBA_PARTIALATTRIBUTESET}
    1768             : };
    1769             : 
    1770    60158360 : const struct ldb_schema_syntax *ldb_samba_syntax_by_name(struct ldb_context *ldb, const char *name)
    1771             : {
    1772     1177086 :         unsigned int j;
    1773    60158360 :         const struct ldb_schema_syntax *s = NULL;
    1774             : 
    1775   894534418 :         for (j=0; j < ARRAY_SIZE(samba_syntaxes); j++) {
    1776   874432291 :                 if (strcmp(name, samba_syntaxes[j].name) == 0) {
    1777    40056233 :                         s = &samba_syntaxes[j];
    1778    40056233 :                         break;
    1779             :                 }
    1780             :         }
    1781    60158360 :         return s;
    1782             : }
    1783             : 
    1784    39741254 : const struct ldb_schema_syntax *ldb_samba_syntax_by_lDAPDisplayName(struct ldb_context *ldb, const char *name)
    1785             : {
    1786      487620 :         unsigned int j;
    1787    39741254 :         const struct ldb_schema_syntax *s = NULL;
    1788             : 
    1789  2374586852 :         for (j=0; j < ARRAY_SIZE(samba_attributes); j++) {
    1790  2336472039 :                 if (strcmp(samba_attributes[j].name, name) == 0) {
    1791     1626441 :                         s = ldb_samba_syntax_by_name(ldb, samba_attributes[j].syntax);
    1792     1626441 :                         break;
    1793             :                 }
    1794             :         }
    1795             : 
    1796    39741254 :         return s;
    1797             : }
    1798             : 
    1799             : static const char *secret_attributes[] = {DSDB_SECRET_ATTRIBUTES, "secret",
    1800             :                                           "priorSecret", NULL};
    1801             : 
    1802             : /*
    1803             :   register the samba ldif handlers
    1804             : */
    1805      521881 : int ldb_register_samba_handlers(struct ldb_context *ldb)
    1806             : {
    1807       17570 :         unsigned int i;
    1808       17570 :         int ret;
    1809             : 
    1810      521881 :         if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
    1811      175517 :                 return LDB_SUCCESS;
    1812             :         }
    1813             : 
    1814      340285 :         ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
    1815      340285 :         if (ret != LDB_SUCCESS) {
    1816           0 :                 return ret;
    1817             :         }
    1818             : 
    1819    20757385 :         for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
    1820    20417100 :                 const struct ldb_schema_syntax *s = NULL;
    1821             : 
    1822    20417100 :                 s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);
    1823             : 
    1824    20417100 :                 if (!s) {
    1825           0 :                         s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
    1826             :                 }
    1827             : 
    1828    20417100 :                 if (!s) {
    1829           0 :                         return LDB_ERR_OPERATIONS_ERROR;
    1830             :                 }
    1831             : 
    1832    20417100 :                 ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
    1833    20417100 :                 if (ret != LDB_SUCCESS) {
    1834           0 :                         return ret;
    1835             :                 }
    1836             :         }
    1837             : 
    1838     3743135 :         for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
    1839     3402850 :                 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
    1840     3402850 :                 if (ret != LDB_SUCCESS) {
    1841           0 :                         return ret;
    1842             :                 }
    1843             : 
    1844             :         }
    1845             : 
    1846      340285 :         ret = ldb_register_samba_matching_rules(ldb);
    1847      340285 :         if (ret != LDB_SUCCESS) {
    1848           0 :                 talloc_free(ldb);
    1849           0 :                 return LDB_SUCCESS;
    1850             :         }
    1851             : 
    1852      340285 :         ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
    1853      340285 :         if (ret != LDB_SUCCESS) {
    1854           0 :                 return ret;
    1855             :         }
    1856             : 
    1857      328794 :         return LDB_SUCCESS;
    1858             : }

Generated by: LCOV version 1.14