LCOV - code coverage report
Current view: top level - lib/ldb-samba - ldif_handlers.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 409 621 65.9 %
Date: 2024-02-14 10:14:15 Functions: 45 55 81.8 %

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

Generated by: LCOV version 1.14