LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules - extended_dn_out.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 255 315 81.0 %
Date: 2024-02-28 12:06:22 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /* 
       2             :    ldb database library
       3             : 
       4             :    Copyright (C) Simo Sorce 2005-2008
       5             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007-2009
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : /*
      22             :  *  Name: ldb
      23             :  *
      24             :  *  Component: ldb extended dn control module
      25             :  *
      26             :  *  Description: this module builds a special dn for returned search
      27             :  *  results, and fixes some other aspects of the result (returned case issues)
      28             :  *  values.
      29             :  *
      30             :  *  Authors: Simo Sorce
      31             :  *           Andrew Bartlett
      32             :  */
      33             : 
      34             : #include "includes.h"
      35             : #include <ldb.h>
      36             : #include <ldb_errors.h>
      37             : #include <ldb_module.h>
      38             : #include "libcli/security/security.h"
      39             : #include "librpc/gen_ndr/ndr_misc.h"
      40             : #include "librpc/gen_ndr/ndr_security.h"
      41             : #include "librpc/ndr/libndr.h"
      42             : #include "dsdb/samdb/samdb.h"
      43             : #include "dsdb/samdb/ldb_modules/util.h"
      44             : 
      45             : #undef strcasecmp
      46             : #undef strncasecmp
      47             : 
      48             : struct extended_dn_out_private {
      49             :         bool dereference;
      50             :         bool normalise;
      51             :         const char **attrs;
      52             : };
      53             : 
      54    24885169 : static char **copy_attrs(void *mem_ctx, const char * const * attrs)
      55             : {
      56     1337877 :         char **nattrs;
      57     1337877 :         unsigned int i, num;
      58             : 
      59    52094889 :         for (num = 0; attrs[num]; num++);
      60             : 
      61    24885169 :         nattrs = talloc_array(mem_ctx, char *, num + 1);
      62    24885169 :         if (!nattrs) return NULL;
      63             : 
      64    52094889 :         for(i = 0; i < num; i++) {
      65    27209720 :                 nattrs[i] = talloc_strdup(nattrs, attrs[i]);
      66    27209720 :                 if (!nattrs[i]) {
      67           0 :                         talloc_free(nattrs);
      68           0 :                         return NULL;
      69             :                 }
      70             :         }
      71    24885169 :         nattrs[i] = NULL;
      72             : 
      73    24885169 :         return nattrs;
      74             : }
      75             : 
      76    48314176 : static bool add_attrs(void *mem_ctx, char ***attrs, const char *attr)
      77             : {
      78     2624373 :         char **nattrs;
      79     2624373 :         unsigned int num;
      80             : 
      81   116716666 :         for (num = 0; (*attrs)[num]; num++);
      82             : 
      83    48314176 :         nattrs = talloc_realloc(mem_ctx, *attrs, char *, num + 2);
      84    48314176 :         if (!nattrs) return false;
      85             : 
      86    48314176 :         *attrs = nattrs;
      87             : 
      88    48314176 :         nattrs[num] = talloc_strdup(nattrs, attr);
      89    48314176 :         if (!nattrs[num]) return false;
      90             : 
      91    48314176 :         nattrs[num + 1] = NULL;
      92             : 
      93    48314176 :         return true;
      94             : }
      95             : 
      96             : /* Inject the extended DN components, so the DN cn=Administrator,cn=users,dc=samba,dc=example,dc=com becomes
      97             :    <GUID=541203ae-f7d6-47ef-8390-bfcf019f9583>;<SID=S-1-5-21-4177067393-1453636373-93818737-500>;cn=Administrator,cn=users,dc=samba,dc=example,dc=com */
      98             : 
      99    71630170 : static int inject_extended_dn_out(struct ldb_reply *ares,
     100             :                                   struct ldb_context *ldb,
     101             :                                   int type,
     102             :                                   bool remove_guid,
     103             :                                   bool remove_sid)
     104             : {
     105     1803357 :         int ret;
     106     1803357 :         const DATA_BLOB *guid_blob;
     107     1803357 :         const DATA_BLOB *sid_blob;
     108             : 
     109    71630170 :         guid_blob = ldb_msg_find_ldb_val(ares->message, "objectGUID");
     110    71630170 :         sid_blob = ldb_msg_find_ldb_val(ares->message, "objectSid");
     111             : 
     112    71630170 :         if (!guid_blob) {
     113           0 :                 ldb_set_errstring(ldb, "Did not find objectGUID to inject into extended DN");
     114           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     115             :         }
     116             : 
     117    71630170 :         ret = ldb_dn_set_extended_component(ares->message->dn, "GUID", guid_blob);
     118    71630170 :         if (ret != LDB_SUCCESS) {
     119           0 :                 return ret;
     120             :         }
     121    71630170 :         if (sid_blob) {
     122     9465954 :                 ret = ldb_dn_set_extended_component(ares->message->dn, "SID", sid_blob);
     123     9465954 :                 if (ret != LDB_SUCCESS) {
     124           0 :                         return ret;
     125             :                 }
     126             :         }
     127             : 
     128    71630170 :         if (remove_guid) {
     129    22289841 :                 ldb_msg_remove_attr(ares->message, "objectGUID");
     130             :         }
     131             : 
     132    71630170 :         if (sid_blob && remove_sid) {
     133     8706887 :                 ldb_msg_remove_attr(ares->message, "objectSid");
     134             :         }
     135             : 
     136    69826813 :         return LDB_SUCCESS;
     137             : }
     138             : 
     139             : /* search */
     140             : struct extended_search_context {
     141             :         struct ldb_module *module;
     142             :         const struct dsdb_schema *schema;
     143             :         struct ldb_request *req;
     144             :         bool inject;
     145             :         bool remove_guid;
     146             :         bool remove_sid;
     147             :         int extended_type;
     148             : };
     149             : 
     150             : 
     151             : /*
     152             :    fix one-way links to have the right string DN, to cope with
     153             :    renames of the target
     154             : */
     155    10670631 : static int fix_one_way_link(struct extended_search_context *ac, struct ldb_dn *dn,
     156             :                             bool is_deleted_objects, bool *remove_value,
     157             :                             uint32_t linkID)
     158             : {
     159       83701 :         struct GUID guid;
     160       83701 :         NTSTATUS status;
     161       83701 :         int ret;
     162       83701 :         struct ldb_dn *real_dn;
     163       83701 :         uint32_t search_flags;
     164    10670631 :         TALLOC_CTX *tmp_ctx = talloc_new(ac);
     165    10670631 :         const char *attrs[] = { NULL };
     166       83701 :         struct ldb_result *res;
     167             : 
     168    10670631 :         (*remove_value) = false;
     169             : 
     170    10670631 :         status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
     171    10670631 :         if (!NT_STATUS_IS_OK(status)) {
     172             :                 /* this is a strange DN that doesn't have a GUID! just
     173             :                    return the current DN string?? */
     174       39989 :                 talloc_free(tmp_ctx);
     175       39989 :                 return LDB_SUCCESS;
     176             :         }
     177             : 
     178    10630642 :         search_flags = DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SEARCH_ALL_PARTITIONS | DSDB_SEARCH_ONE_ONLY;
     179             : 
     180    10630642 :         if (linkID == 0) {
     181             :                 /* You must ALWAYS show one-way links regardless of the state of the target */
     182    10258265 :                 search_flags |= (DSDB_SEARCH_SHOW_DELETED | DSDB_SEARCH_SHOW_RECYCLED);
     183             :         }
     184             : 
     185    10630642 :         ret = dsdb_module_search(ac->module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
     186             :                                  search_flags, ac->req, "objectguid=%s", GUID_string(tmp_ctx, &guid));
     187    10630642 :         if (ret != LDB_SUCCESS || res->count != 1) {
     188             :                 /* if we can't resolve this GUID, then we don't
     189             :                    display the link. This could be a link to a NC that we don't
     190             :                    have, or it could be a link to a deleted object
     191             :                 */
     192        5679 :                 (*remove_value) = true;
     193        5679 :                 talloc_free(tmp_ctx);
     194        5679 :                 return LDB_SUCCESS;
     195             :         }
     196    10624963 :         real_dn = res->msgs[0]->dn;
     197             : 
     198    10624963 :         if (strcmp(ldb_dn_get_linearized(dn), ldb_dn_get_linearized(real_dn)) == 0) {
     199             :                 /* its already correct */
     200    10493206 :                 talloc_free(tmp_ctx);
     201    10493206 :                 return LDB_SUCCESS;
     202             :         }
     203             : 
     204             :         /* fix the DN by replacing its components with those from the
     205             :          * real DN
     206             :          */
     207      131757 :         if (!ldb_dn_replace_components(dn, real_dn)) {
     208           0 :                 talloc_free(tmp_ctx);
     209           0 :                 return ldb_operr(ldb_module_get_ctx(ac->module));
     210             :         }
     211      131757 :         talloc_free(tmp_ctx);
     212             : 
     213      131757 :         return LDB_SUCCESS;
     214             : }
     215             : 
     216             : 
     217             : /*
     218             :   this is called to post-process the results from the search
     219             :  */
     220   134602043 : static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
     221             : {
     222     4949959 :         struct extended_search_context *ac;
     223     4949959 :         int ret;
     224     4949959 :         unsigned int i, j, k;
     225     4949959 :         struct ldb_message *msg;
     226     4949959 :         struct extended_dn_out_private *p;
     227     4949959 :         struct ldb_context *ldb;
     228   134602043 :         bool have_reveal_control=false;
     229             : 
     230   134602043 :         ac = talloc_get_type(req->context, struct extended_search_context);
     231   134602043 :         p = talloc_get_type(ldb_module_get_private(ac->module), struct extended_dn_out_private);
     232   134602043 :         ldb = ldb_module_get_ctx(ac->module);
     233   134602043 :         if (!ares) {
     234           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     235             :                                         LDB_ERR_OPERATIONS_ERROR);
     236             :         }
     237   134602043 :         if (ares->error != LDB_SUCCESS) {
     238     2172173 :                 return ldb_module_done(ac->req, ares->controls,
     239             :                                         ares->response, ares->error);
     240             :         }
     241             : 
     242   132429870 :         msg = ares->message;
     243             : 
     244   132429870 :         switch (ares->type) {
     245     4150914 :         case LDB_REPLY_REFERRAL:
     246     4150914 :                 return ldb_module_send_referral(ac->req, ares->referral);
     247             : 
     248    40347487 :         case LDB_REPLY_DONE:
     249    40347487 :                 return ldb_module_done(ac->req, ares->controls,
     250             :                                         ares->response, LDB_SUCCESS);
     251    85344750 :         case LDB_REPLY_ENTRY:
     252    85344750 :                 break;
     253             :         }
     254             : 
     255    87931469 :         if (p && p->normalise) {
     256           0 :                 ret = dsdb_fix_dn_rdncase(ldb, ares->message->dn);
     257           0 :                 if (ret != LDB_SUCCESS) {
     258           0 :                         return ldb_module_done(ac->req, NULL, NULL, ret);
     259             :                 }
     260             :         }
     261             :                         
     262    87931469 :         if (ac->inject) {
     263             :                 /* for each record returned post-process to add any derived
     264             :                    attributes that have been asked for */
     265    73433527 :                 ret = inject_extended_dn_out(ares, ldb,
     266    71630170 :                                              ac->extended_type, ac->remove_guid,
     267    71630170 :                                              ac->remove_sid);
     268    71630170 :                 if (ret != LDB_SUCCESS) {
     269           0 :                         return ldb_module_done(ac->req, NULL, NULL, ret);
     270             :                 }
     271             :         }
     272             : 
     273    87931469 :         if ((p && p->normalise) || ac->inject) {
     274    71630170 :                 const struct ldb_val *val = ldb_msg_find_ldb_val(ares->message, "distinguishedName");
     275    71630170 :                 if (val) {
     276     1968170 :                         ldb_msg_remove_attr(ares->message, "distinguishedName");
     277     1968170 :                         if (ac->inject) {
     278     1968170 :                                 ret = ldb_msg_add_steal_string(ares->message, "distinguishedName", 
     279     1968170 :                                                                ldb_dn_get_extended_linearized(ares->message, ares->message->dn, ac->extended_type));
     280             :                         } else {
     281           0 :                                 ret = ldb_msg_add_linearized_dn(ares->message,
     282             :                                                                 "distinguishedName",
     283           0 :                                                                 ares->message->dn);
     284             :                         }
     285     1968170 :                         if (ret != LDB_SUCCESS) {
     286           0 :                                 return ldb_oom(ldb);
     287             :                         }
     288             :                 }
     289             :         }
     290             : 
     291     2586719 :         have_reveal_control =
     292    87931469 :                 dsdb_request_has_control(req, LDB_CONTROL_REVEAL_INTERNALS);
     293             : 
     294             :         /* 
     295             :          * Shortcut for repl_meta_data.  We asked for the data
     296             :          * 'as-is', so stop processing here!
     297             :          */
     298    87931469 :         if (have_reveal_control && (p == NULL || !p->normalise) && ac->inject) {
     299     4583010 :                 return ldb_module_send_entry(ac->req, msg, ares->controls);
     300             :         }
     301             :         
     302             :         /* Walk the returned elements (but only if we have a schema to
     303             :          * interpret the list with) */
     304   633548955 :         for (i = 0; ac->schema && i < msg->num_elements; i++) {
     305     4474458 :                 bool make_extended_dn;
     306   550200496 :                 bool bl_requested = true;
     307     4474458 :                 const struct dsdb_attribute *attribute;
     308             : 
     309   550200496 :                 attribute = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name);
     310   550200496 :                 if (!attribute) {
     311           0 :                         continue;
     312             :                 }
     313             : 
     314   550200496 :                 if (p && p->normalise) {
     315             :                         /* If we are also in 'normalise' mode, then
     316             :                          * fix the attribute names to be in the
     317             :                          * correct case */
     318           0 :                         msg->elements[i].name = talloc_strdup(msg->elements, attribute->lDAPDisplayName);
     319           0 :                         if (!msg->elements[i].name) {
     320           0 :                                 ldb_oom(ldb);
     321           0 :                                 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
     322             :                         }
     323             :                 }
     324             : 
     325             :                 /* distinguishedName has been dealt with above */
     326   550200496 :                 if (ldb_attr_cmp(msg->elements[i].name, "distinguishedName") == 0) {
     327     2170668 :                         continue;
     328             :                 }
     329             : 
     330             :                 /* Look to see if this attributeSyntax is a DN */
     331   548029828 :                 if (attribute->dn_format == DSDB_INVALID_DN) {
     332   537298545 :                         continue;
     333             :                 }
     334             : 
     335    10731283 :                 make_extended_dn = ac->inject;
     336             : 
     337             :                 /* Always show plain DN in case of Object(OR-Name) syntax */
     338    10731283 :                 if (make_extended_dn) {
     339     6881224 :                         make_extended_dn = (strcmp(attribute->syntax->ldap_oid, DSDB_SYNTAX_OR_NAME) != 0);
     340             :                 }
     341             : 
     342    10731283 :                 if (attribute->linkID & 1 &&
     343     1930728 :                     attribute->bl_maybe_invisible &&
     344         439 :                     !have_reveal_control)
     345             :                 {
     346         188 :                         const char * const *attrs = ac->req->op.search.attrs;
     347             : 
     348         188 :                         if (attrs != NULL) {
     349         182 :                                 bl_requested = ldb_attr_in_list(attrs,
     350         182 :                                                 attribute->lDAPDisplayName);
     351             :                         } else {
     352           6 :                                 bl_requested = false;
     353             :                         }
     354             :                 }
     355             : 
     356    30211626 :                 for (k = 0, j = 0; j < msg->elements[i].num_values; j++) {
     357      434487 :                         const char *dn_str;
     358      434487 :                         struct ldb_dn *dn;
     359    19480343 :                         struct dsdb_dn *dsdb_dn = NULL;
     360    19480343 :                         struct ldb_val *plain_dn = &msg->elements[i].values[j];
     361    19480343 :                         bool is_deleted_objects = false;
     362      434487 :                         uint32_t rmd_flags;
     363             : 
     364             :                         /* this is a fast method for detecting deleted
     365             :                            linked attributes, working on the unparsed
     366             :                            ldb_val */
     367    19480343 :                         rmd_flags = dsdb_dn_val_rmd_flags(plain_dn);
     368    19480343 :                         if (rmd_flags & DSDB_RMD_FLAG_DELETED && !have_reveal_control) {
     369             :                                 /* it's a deleted linked attribute,
     370             :                                   and we don't have the reveal control */
     371             :                                 /* we won't keep this one, so not incrementing k */
     372      163328 :                                 continue;
     373             :                         }
     374    19317015 :                         if (rmd_flags & DSDB_RMD_FLAG_HIDDEN_BL && !bl_requested) {
     375             :                                 /*
     376             :                                  * Hidden backlinks are not revealed unless
     377             :                                  * requested.
     378             :                                  *
     379             :                                  * we won't keep this one, so not incrementing k
     380             :                                  */
     381          20 :                                 continue;
     382             :                         }
     383             : 
     384    19316995 :                         dsdb_dn = dsdb_dn_parse_trusted(msg, ldb, plain_dn, attribute->syntax->ldap_oid);
     385             : 
     386    19316995 :                         if (!dsdb_dn) {
     387           0 :                                 ldb_asprintf_errstring(ldb,
     388             :                                                        "could not parse %.*s in %s on %s as a %s DN",
     389           0 :                                                        (int)plain_dn->length, plain_dn->data,
     390           0 :                                                        msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
     391           0 :                                                        attribute->syntax->ldap_oid);
     392           0 :                                 talloc_free(dsdb_dn);
     393           0 :                                 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX);
     394             :                         }
     395    19316995 :                         dn = dsdb_dn->dn;
     396             : 
     397             :                         /* we need to know if this is a link to the
     398             :                            deleted objects container for fixing one way
     399             :                            links */
     400    19316995 :                         if (dsdb_dn->extra_part.length == 16) {
     401     4703965 :                                 char *hex_string = data_blob_hex_string_upper(req, &dsdb_dn->extra_part);
     402     4703965 :                                 if (hex_string && strcmp(hex_string, DS_GUID_DELETED_OBJECTS_CONTAINER) == 0) {
     403      400545 :                                         is_deleted_objects = true;
     404             :                                 }
     405     4703965 :                                 talloc_free(hex_string);
     406             :                         }
     407             : 
     408    19316995 :                         if (p != NULL && p->normalise) {
     409           0 :                                 ret = dsdb_fix_dn_rdncase(ldb, dn);
     410           0 :                                 if (ret != LDB_SUCCESS) {
     411           0 :                                         talloc_free(dsdb_dn);
     412           0 :                                         return ldb_module_done(ac->req, NULL, NULL, ret);
     413             :                                 }
     414             :                         }
     415             : 
     416             :                         /* Look for this value in the attribute */
     417             : 
     418             :                         /* note that we don't fixup objectCategory as
     419             :                            it should not be possible to move
     420             :                            objectCategory elements in the schema */
     421    19316995 :                         if (attribute->one_way_link &&
     422    10670631 :                             strcasecmp(attribute->lDAPDisplayName, "objectCategory") != 0) {
     423       83701 :                                 bool remove_value;
     424    10754332 :                                 ret = fix_one_way_link(ac, dn, is_deleted_objects, &remove_value,
     425    10670631 :                                                        attribute->linkID);
     426    10670631 :                                 if (ret != LDB_SUCCESS) {
     427           0 :                                         talloc_free(dsdb_dn);
     428           0 :                                         return ldb_module_done(ac->req, NULL, NULL, ret);
     429             :                                 }
     430    10670631 :                                 if (remove_value && !have_reveal_control) {
     431             :                                         /* we show these with REVEAL
     432             :                                            to allow dbcheck to find and
     433             :                                            cleanup these orphaned links */
     434             :                                         /* we won't keep this one, so not incrementing k */
     435        5136 :                                         continue;
     436             :                                 }
     437             :                         }
     438             :                         
     439    19311859 :                         if (make_extended_dn) {
     440    14276265 :                                 if (!ldb_dn_validate(dsdb_dn->dn)) {
     441           0 :                                         ldb_asprintf_errstring(ldb, 
     442             :                                                                "could not parse %.*s in %s on %s as a %s DN", 
     443           0 :                                                                (int)plain_dn->length, plain_dn->data,
     444           0 :                                                                msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
     445           0 :                                                                attribute->syntax->ldap_oid);
     446           0 :                                         talloc_free(dsdb_dn);
     447           0 :                                         return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX);
     448             :                                 }
     449             :                                 /* don't let users see the internal extended
     450             :                                    GUID components */
     451    14276265 :                                 if (!have_reveal_control) {
     452    14276265 :                                         const char *accept[] = { "GUID", "SID", NULL };
     453    14276265 :                                         ldb_dn_extended_filter(dn, accept);
     454             :                                 }
     455    14276265 :                                 dn_str = dsdb_dn_get_extended_linearized(msg->elements[i].values,
     456             :                                                                          dsdb_dn, ac->extended_type);
     457             :                         } else {
     458     5035594 :                                 dn_str = dsdb_dn_get_linearized(msg->elements[i].values,
     459             :                                                                 dsdb_dn);
     460             :                         }
     461             : 
     462    19311859 :                         if (!dn_str) {
     463           0 :                                 ldb_oom(ldb);
     464           0 :                                 talloc_free(dsdb_dn);
     465           0 :                                 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
     466             :                         }
     467    19311859 :                         msg->elements[i].values[k] = data_blob_string_const(dn_str);
     468    19311859 :                         talloc_free(dsdb_dn);
     469    19311859 :                         k++;
     470             :                 }
     471             : 
     472    10731283 :                 if (k == 0) {
     473             :                         /* we've deleted all of the values from this
     474             :                          * element - remove the element */
     475        1700 :                         ldb_msg_remove_element(msg, &msg->elements[i]);
     476        1700 :                         i--;
     477             :                 } else {
     478    10729583 :                         msg->elements[i].num_values = k;
     479             :                 }
     480             :         }
     481    83348459 :         return ldb_module_send_entry(ac->req, msg, ares->controls);
     482             : }
     483             : 
     484   134602043 : static int extended_callback_ldb(struct ldb_request *req, struct ldb_reply *ares)
     485             : {
     486   134602043 :         return extended_callback(req, ares);
     487             : }
     488             : 
     489    44429120 : static int extended_dn_out_search(struct ldb_module *module, struct ldb_request *req,
     490             :                 int (*callback)(struct ldb_request *req, struct ldb_reply *ares))
     491             : {
     492     2320569 :         struct ldb_control *control;
     493     2320569 :         struct ldb_control *storage_format_control;
     494    44429120 :         struct ldb_extended_dn_control *extended_ctrl = NULL;
     495     2320569 :         struct extended_search_context *ac;
     496     2320569 :         struct ldb_request *down_req;
     497     2320569 :         char **new_attrs;
     498     2320569 :         const char * const *const_attrs;
     499    44429120 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     500     2320569 :         int ret;
     501             : 
     502    44429120 :         struct extended_dn_out_private *p = talloc_get_type(ldb_module_get_private(module), struct extended_dn_out_private);
     503             : 
     504             :         /* The schema manipulation does not apply to special DNs */
     505    44429120 :         if (ldb_dn_is_special(req->op.search.base)) {
     506     1856022 :                 return ldb_next_request(module, req);
     507             :         }
     508             : 
     509             :         /* check if there's an extended dn control */
     510    42573098 :         control = ldb_request_get_control(req, LDB_CONTROL_EXTENDED_DN_OID);
     511    42573098 :         if (control && control->data) {
     512    19611750 :                 extended_ctrl = talloc_get_type(control->data, struct ldb_extended_dn_control);
     513    19611750 :                 if (!extended_ctrl) {
     514           0 :                         return LDB_ERR_PROTOCOL_ERROR;
     515             :                 }
     516             :         }
     517             : 
     518             :         /* Look to see if, as we are in 'store DN+GUID+SID' mode, the
     519             :          * client is after the storage format (to fill in linked
     520             :          * attributes) */
     521    42573098 :         storage_format_control = ldb_request_get_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID);
     522    42573098 :         if (!control && storage_format_control && storage_format_control->data) {
     523           0 :                 extended_ctrl = talloc_get_type(storage_format_control->data, struct ldb_extended_dn_control);
     524           0 :                 if (!extended_ctrl) {
     525           0 :                         ldb_set_errstring(ldb, "extended_dn_out: extended_ctrl was of the wrong data type");
     526           0 :                         return LDB_ERR_PROTOCOL_ERROR;
     527             :                 }
     528             :         }
     529             : 
     530    42573098 :         ac = talloc_zero(req, struct extended_search_context);
     531    42573098 :         if (ac == NULL) {
     532           0 :                 return ldb_oom(ldb);
     533             :         }
     534             : 
     535    42573098 :         ac->module = module;
     536    42573098 :         ac->schema = dsdb_get_schema(ldb, ac);
     537    42573098 :         ac->req = req;
     538    42573098 :         ac->inject = false;
     539    42573098 :         ac->remove_guid = false;
     540    42573098 :         ac->remove_sid = false;
     541             :         
     542    42573098 :         const_attrs = req->op.search.attrs;
     543             : 
     544             :         /* We only need to do special processing if we were asked for
     545             :          * the extended DN, or we are 'store DN+GUID+SID'
     546             :          * (!dereference) mode.  (This is the normal mode for LDB on
     547             :          * tdb). */
     548    42573098 :         if (control || (storage_format_control && p)) {
     549    27182308 :                 ac->inject = true;
     550    27182308 :                 if (extended_ctrl) {
     551    19611750 :                         ac->extended_type = extended_ctrl->type;
     552             :                 } else {
     553     7570558 :                         ac->extended_type = 0;
     554             :                 }
     555             : 
     556             :                 /* check if attrs only is specified, in that case check whether we need to modify them */
     557    27182308 :                 if (req->op.search.attrs && !ldb_attr_in_list(req->op.search.attrs, "*")) {
     558    25217203 :                         if (! ldb_attr_in_list(req->op.search.attrs, "objectGUID")) {
     559    23601635 :                                 ac->remove_guid = true;
     560             :                         }
     561    25217203 :                         if (! ldb_attr_in_list(req->op.search.attrs, "objectSid")) {
     562    24712541 :                                 ac->remove_sid = true;
     563             :                         }
     564    25217203 :                         if (ac->remove_guid || ac->remove_sid) {
     565    24885169 :                                 new_attrs = copy_attrs(ac, req->op.search.attrs);
     566    24885169 :                                 if (new_attrs == NULL) {
     567           0 :                                         return ldb_oom(ldb);
     568             :                                 }
     569             : 
     570    24885169 :                                 if (ac->remove_guid) {
     571    23601635 :                                         if (!add_attrs(ac, &new_attrs, "objectGUID"))
     572           0 :                                                 return ldb_operr(ldb);
     573             :                                 }
     574    24885169 :                                 if (ac->remove_sid) {
     575    24712541 :                                         if (!add_attrs(ac, &new_attrs, "objectSid"))
     576           0 :                                                 return ldb_operr(ldb);
     577             :                                 }
     578    24885169 :                                 const_attrs = (const char * const *)new_attrs;
     579             :                         }
     580             :                 }
     581             :         }
     582             : 
     583    42573098 :         ret = ldb_build_search_req_ex(&down_req,
     584             :                                       ldb, ac,
     585             :                                       req->op.search.base,
     586             :                                       req->op.search.scope,
     587             :                                       req->op.search.tree,
     588             :                                       const_attrs,
     589             :                                       req->controls,
     590             :                                       ac, callback,
     591             :                                       req);
     592    42573098 :         LDB_REQ_SET_LOCATION(down_req);
     593    42573098 :         if (ret != LDB_SUCCESS) {
     594           0 :                 return ret;
     595             :         }
     596             : 
     597             :         /* mark extended DN and storage format controls as done */
     598    42573098 :         if (control) {
     599    20261759 :                 control->critical = 0;
     600             :         }
     601             : 
     602    42573098 :         if (storage_format_control) {
     603     7460370 :                 storage_format_control->critical = 0;
     604             :         }
     605             : 
     606             :         /* perform the search */
     607    42573098 :         return ldb_next_request(module, down_req);
     608             : }
     609             : 
     610    44429120 : static int extended_dn_out_ldb_search(struct ldb_module *module, struct ldb_request *req)
     611             : {
     612    44429120 :         return extended_dn_out_search(module, req, extended_callback_ldb);
     613             : }
     614             : 
     615      180264 : static int extended_dn_out_ldb_init(struct ldb_module *module)
     616             : {
     617        6014 :         int ret;
     618             : 
     619      180264 :         struct extended_dn_out_private *p = talloc(module, struct extended_dn_out_private);
     620        6014 :         struct dsdb_extended_dn_store_format *dn_format;
     621             : 
     622      180264 :         ldb_module_set_private(module, p);
     623             : 
     624      180264 :         if (!p) {
     625           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     626             :         }
     627             : 
     628      180264 :         dn_format = talloc(p, struct dsdb_extended_dn_store_format);
     629      180264 :         if (!dn_format) {
     630           0 :                 talloc_free(p);
     631           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     632             :         }
     633             : 
     634      180264 :         dn_format->store_extended_dn_in_ldb = true;
     635      180264 :         ret = ldb_set_opaque(ldb_module_get_ctx(module), DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME, dn_format);
     636      180264 :         if (ret != LDB_SUCCESS) {
     637           0 :                 talloc_free(p);
     638           0 :                 return ret;
     639             :         }
     640             : 
     641      180264 :         p->dereference = false;
     642      180264 :         p->normalise = false;
     643             : 
     644      180264 :         ret = ldb_mod_register_control(module, LDB_CONTROL_EXTENDED_DN_OID);
     645      180264 :         if (ret != LDB_SUCCESS) {
     646           0 :                 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
     647             :                         "extended_dn_out: Unable to register control with rootdse!\n");
     648           0 :                 return ldb_operr(ldb_module_get_ctx(module));
     649             :         }
     650             : 
     651      180264 :         return ldb_next_init(module);
     652             : }
     653             : 
     654             : static const struct ldb_module_ops ldb_extended_dn_out_ldb_module_ops = {
     655             :         .name              = "extended_dn_out_ldb",
     656             :         .search            = extended_dn_out_ldb_search,
     657             :         .init_context      = extended_dn_out_ldb_init,
     658             : };
     659             : 
     660             : /*
     661             :   initialise the module
     662             :  */
     663        5922 : _PUBLIC_ int ldb_extended_dn_out_module_init(const char *version)
     664             : {
     665         393 :         int ret;
     666        5922 :         LDB_MODULE_CHECK_VERSION(version);
     667        5922 :         ret = ldb_register_module(&ldb_extended_dn_out_ldb_module_ops);
     668        5922 :         if (ret != LDB_SUCCESS) {
     669           0 :                 return ret;
     670             :         }
     671        5529 :         return LDB_SUCCESS;
     672             : }

Generated by: LCOV version 1.14