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

Generated by: LCOV version 1.14