LCOV - code coverage report
Current view: top level - lib/ldb-samba - ldif_handlers.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 439 623 70.5 %
Date: 2021-09-23 10:06:22 Functions: 48 55 87.3 %

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

Generated by: LCOV version 1.13