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 abartlet/fix-coverage dd10fb34 Lines: 209 269 77.7 %
Date: 2021-09-23 10: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     9490190 : static char **copy_attrs(void *mem_ctx, const char * const * attrs)
      55             : {
      56             :         char **nattrs;
      57             :         unsigned int i, num;
      58             : 
      59    11770655 :         for (num = 0; attrs[num]; num++);
      60             : 
      61     9490190 :         nattrs = talloc_array(mem_ctx, char *, num + 1);
      62     9490190 :         if (!nattrs) return NULL;
      63             : 
      64    23261559 :         for(i = 0; i < num; i++) {
      65    14190395 :                 nattrs[i] = talloc_strdup(nattrs, attrs[i]);
      66    14190395 :                 if (!nattrs[i]) {
      67           0 :                         talloc_free(nattrs);
      68           0 :                         return NULL;
      69             :                 }
      70             :         }
      71     9490190 :         nattrs[i] = NULL;
      72             : 
      73     9490190 :         return nattrs;
      74             : }
      75             : 
      76    18115833 : static bool add_attrs(void *mem_ctx, char ***attrs, const char *attr)
      77             : {
      78             :         char **nattrs;
      79             :         unsigned int num;
      80             : 
      81    22864315 :         for (num = 0; (*attrs)[num]; num++);
      82             : 
      83    18115833 :         nattrs = talloc_realloc(mem_ctx, *attrs, char *, num + 2);
      84    18115833 :         if (!nattrs) return false;
      85             : 
      86    18115833 :         *attrs = nattrs;
      87             : 
      88    18115833 :         nattrs[num] = talloc_strdup(nattrs, attr);
      89    18115833 :         if (!nattrs[num]) return false;
      90             : 
      91    18115833 :         nattrs[num + 1] = NULL;
      92             : 
      93    18115833 :         return true;
      94             : }
      95             : 
      96             : /* Inject the extended DN components, so the DN cn=Adminstrator,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=Adminstrator,cn=users,dc=samba,dc=example,dc=com */
      98             : 
      99    47357945 : 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             :         int ret;
     106             :         const DATA_BLOB *guid_blob;
     107             :         const DATA_BLOB *sid_blob;
     108             : 
     109    47357945 :         guid_blob = ldb_msg_find_ldb_val(ares->message, "objectGUID");
     110    47357945 :         sid_blob = ldb_msg_find_ldb_val(ares->message, "objectSid");
     111             : 
     112    47357945 :         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    47357945 :         ret = ldb_dn_set_extended_component(ares->message->dn, "GUID", guid_blob);
     118    47357945 :         if (ret != LDB_SUCCESS) {
     119           0 :                 return ret;
     120             :         }
     121    47357945 :         if (sid_blob) {
     122     4304940 :                 ret = ldb_dn_set_extended_component(ares->message->dn, "SID", sid_blob);
     123     4304940 :                 if (ret != LDB_SUCCESS) {
     124           0 :                         return ret;
     125             :                 }
     126             :         }
     127             : 
     128    47357945 :         if (remove_guid) {
     129     8907007 :                 ldb_msg_remove_attr(ares->message, "objectGUID");
     130             :         }
     131             : 
     132    47357945 :         if (sid_blob && remove_sid) {
     133     3792334 :                 ldb_msg_remove_attr(ares->message, "objectSid");
     134             :         }
     135             : 
     136    46288188 :         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     7939956 : 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             :         struct GUID guid;
     160             :         NTSTATUS status;
     161             :         int ret;
     162             :         struct ldb_dn *real_dn;
     163             :         uint32_t search_flags;
     164     7939956 :         TALLOC_CTX *tmp_ctx = talloc_new(ac);
     165     7939956 :         const char *attrs[] = { NULL };
     166             :         struct ldb_result *res;
     167             : 
     168     7939956 :         (*remove_value) = false;
     169             : 
     170     7939956 :         status = dsdb_get_extended_dn_guid(dn, &guid, "GUID");
     171     7939956 :         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       37709 :                 talloc_free(tmp_ctx);
     175       37709 :                 return LDB_SUCCESS;
     176             :         }
     177             : 
     178     7902247 :         search_flags = DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SEARCH_ALL_PARTITIONS | DSDB_SEARCH_ONE_ONLY;
     179             : 
     180     7902247 :         if (linkID == 0) {
     181             :                 /* You must ALWAYS show one-way links regardless of the state of the target */
     182     7609724 :                 search_flags |= (DSDB_SEARCH_SHOW_DELETED | DSDB_SEARCH_SHOW_RECYCLED);
     183             :         }
     184             : 
     185     7902247 :         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     7902247 :         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        6113 :                 (*remove_value) = true;
     193        6113 :                 talloc_free(tmp_ctx);
     194        6113 :                 return LDB_SUCCESS;
     195             :         }
     196     7896134 :         real_dn = res->msgs[0]->dn;
     197             : 
     198     7896134 :         if (strcmp(ldb_dn_get_linearized(dn), ldb_dn_get_linearized(real_dn)) == 0) {
     199             :                 /* its already correct */
     200     7783211 :                 talloc_free(tmp_ctx);
     201     7783211 :                 return LDB_SUCCESS;
     202             :         }
     203             : 
     204             :         /* fix the DN by replacing its components with those from the
     205             :          * real DN
     206             :          */
     207      112923 :         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      112923 :         talloc_free(tmp_ctx);
     212             : 
     213      112923 :         return LDB_SUCCESS;
     214             : }
     215             : 
     216             : 
     217             : /*
     218             :   this is called to post-process the results from the search
     219             :  */
     220    89369262 : static int extended_callback(struct ldb_request *req, struct ldb_reply *ares)
     221             : {
     222             :         struct extended_search_context *ac;
     223             :         int ret;
     224             :         unsigned int i, j, k;
     225             :         struct ldb_message *msg;
     226             :         struct extended_dn_out_private *p;
     227             :         struct ldb_context *ldb;
     228    89369262 :         bool have_reveal_control=false;
     229             : 
     230    89369262 :         ac = talloc_get_type(req->context, struct extended_search_context);
     231    89369262 :         p = talloc_get_type(ldb_module_get_private(ac->module), struct extended_dn_out_private);
     232    89369262 :         ldb = ldb_module_get_ctx(ac->module);
     233    89369262 :         if (!ares) {
     234           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     235             :                                         LDB_ERR_OPERATIONS_ERROR);
     236             :         }
     237    89369262 :         if (ares->error != LDB_SUCCESS) {
     238      338846 :                 return ldb_module_done(ac->req, ares->controls,
     239             :                                         ares->response, ares->error);
     240             :         }
     241             : 
     242    89030416 :         msg = ares->message;
     243             : 
     244    89030416 :         switch (ares->type) {
     245     2425559 :         case LDB_REPLY_REFERRAL:
     246     2425559 :                 return ldb_module_send_referral(ac->req, ares->referral);
     247             : 
     248    24433232 :         case LDB_REPLY_DONE:
     249    24433232 :                 return ldb_module_done(ac->req, ares->controls,
     250             :                                         ares->response, LDB_SUCCESS);
     251    60399761 :         case LDB_REPLY_ENTRY:
     252    60399761 :                 break;
     253             :         }
     254             : 
     255    62171625 :         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    62171625 :         if (ac->inject) {
     263             :                 /* for each record returned post-process to add any derived
     264             :                    attributes that have been asked for */
     265    83110045 :                 ret = inject_extended_dn_out(ares, ldb,
     266    47357945 :                                              ac->extended_type, ac->remove_guid,
     267    47357945 :                                              ac->remove_sid);
     268    47357945 :                 if (ret != LDB_SUCCESS) {
     269           0 :                         return ldb_module_done(ac->req, NULL, NULL, ret);
     270             :                 }
     271             :         }
     272             : 
     273    62171625 :         if ((p && p->normalise) || ac->inject) {
     274    47357945 :                 const struct ldb_val *val = ldb_msg_find_ldb_val(ares->message, "distinguishedName");
     275    47357945 :                 if (val) {
     276     1533295 :                         ldb_msg_remove_attr(ares->message, "distinguishedName");
     277     1533295 :                         if (ac->inject) {
     278     4259651 :                                 ret = ldb_msg_add_steal_string(ares->message, "distinguishedName", 
     279     2856127 :                                                                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     1533295 :                         if (ret != LDB_SUCCESS) {
     286           0 :                                 return ldb_oom(ldb);
     287             :                         }
     288             :                 }
     289             :         }
     290             : 
     291    48336901 :         have_reveal_control =
     292    13834724 :                 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    62171625 :         if (have_reveal_control && p->normalise == false && ac->inject == true) {
     299     3672768 :                 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   474242149 :         for (i = 0; ac->schema && i < msg->num_elements; i++) {
     305             :                 bool make_extended_dn;
     306             :                 const struct dsdb_attribute *attribute;
     307             : 
     308   417301260 :                 attribute = dsdb_attribute_by_lDAPDisplayName(ac->schema, msg->elements[i].name);
     309   417301260 :                 if (!attribute) {
     310           0 :                         continue;
     311             :                 }
     312             : 
     313   417301260 :                 if (p && p->normalise) {
     314             :                         /* If we are also in 'normalise' mode, then
     315             :                          * fix the attribute names to be in the
     316             :                          * correct case */
     317           0 :                         msg->elements[i].name = talloc_strdup(msg->elements, attribute->lDAPDisplayName);
     318           0 :                         if (!msg->elements[i].name) {
     319           0 :                                 ldb_oom(ldb);
     320           0 :                                 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
     321             :                         }
     322             :                 }
     323             : 
     324             :                 /* distinguishedName has been dealt with above */
     325   417301260 :                 if (ldb_attr_cmp(msg->elements[i].name, "distinguishedName") == 0) {
     326     1803996 :                         continue;
     327             :                 }
     328             : 
     329             :                 /* Look to see if this attributeSyntax is a DN */
     330   415497264 :                 if (attribute->dn_format == DSDB_INVALID_DN) {
     331   407466628 :                         continue;
     332             :                 }
     333             : 
     334     8030636 :                 make_extended_dn = ac->inject;
     335             : 
     336             :                 /* Always show plain DN in case of Object(OR-Name) syntax */
     337     8030636 :                 if (make_extended_dn) {
     338     4937943 :                         make_extended_dn = (strcmp(attribute->syntax->ldap_oid, DSDB_SYNTAX_OR_NAME) != 0);
     339             :                 }
     340             : 
     341    20239669 :                 for (k = 0, j = 0; j < msg->elements[i].num_values; j++) {
     342             :                         const char *dn_str;
     343             :                         struct ldb_dn *dn;
     344    12209033 :                         struct dsdb_dn *dsdb_dn = NULL;
     345    12209033 :                         struct ldb_val *plain_dn = &msg->elements[i].values[j];
     346    12209033 :                         bool is_deleted_objects = false;
     347             : 
     348             :                         /* this is a fast method for detecting deleted
     349             :                            linked attributes, working on the unparsed
     350             :                            ldb_val */
     351    12209033 :                         if (dsdb_dn_is_deleted_val(plain_dn) && !have_reveal_control) {
     352             :                                 /* it's a deleted linked attribute,
     353             :                                   and we don't have the reveal control */
     354             :                                 /* we won't keep this one, so not incrementing k */
     355        2355 :                                 continue;
     356             :                         }
     357             : 
     358             : 
     359    12206678 :                         dsdb_dn = dsdb_dn_parse_trusted(msg, ldb, plain_dn, attribute->syntax->ldap_oid);
     360             : 
     361    12206678 :                         if (!dsdb_dn) {
     362           0 :                                 ldb_asprintf_errstring(ldb,
     363             :                                                        "could not parse %.*s in %s on %s as a %s DN",
     364           0 :                                                        (int)plain_dn->length, plain_dn->data,
     365           0 :                                                        msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
     366           0 :                                                        attribute->syntax->ldap_oid);
     367           0 :                                 talloc_free(dsdb_dn);
     368           0 :                                 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX);
     369             :                         }
     370    12206678 :                         dn = dsdb_dn->dn;
     371             : 
     372             :                         /* we need to know if this is a link to the
     373             :                            deleted objects container for fixing one way
     374             :                            links */
     375    12206678 :                         if (dsdb_dn->extra_part.length == 16) {
     376     3430669 :                                 char *hex_string = data_blob_hex_string_upper(req, &dsdb_dn->extra_part);
     377     3430669 :                                 if (hex_string && strcmp(hex_string, DS_GUID_DELETED_OBJECTS_CONTAINER) == 0) {
     378      300220 :                                         is_deleted_objects = true;
     379             :                                 }
     380     3430669 :                                 talloc_free(hex_string);
     381             :                         }
     382             : 
     383    12206678 :                         if (p->normalise) {
     384           0 :                                 ret = dsdb_fix_dn_rdncase(ldb, dn);
     385           0 :                                 if (ret != LDB_SUCCESS) {
     386           0 :                                         talloc_free(dsdb_dn);
     387           0 :                                         return ldb_module_done(ac->req, NULL, NULL, ret);
     388             :                                 }
     389             :                         }
     390             : 
     391             :                         /* Look for this value in the attribute */
     392             : 
     393             :                         /* note that we don't fixup objectCategory as
     394             :                            it should not be possible to move
     395             :                            objectCategory elements in the schema */
     396    18795412 :                         if (attribute->one_way_link &&
     397     7939956 :                             strcasecmp(attribute->lDAPDisplayName, "objectCategory") != 0) {
     398             :                                 bool remove_value;
     399     7939956 :                                 ret = fix_one_way_link(ac, dn, is_deleted_objects, &remove_value,
     400     1351222 :                                                        attribute->linkID);
     401     7939956 :                                 if (ret != LDB_SUCCESS) {
     402           0 :                                         talloc_free(dsdb_dn);
     403           0 :                                         return ldb_module_done(ac->req, NULL, NULL, ret);
     404             :                                 }
     405     7946069 :                                 if (remove_value &&
     406        6113 :                                     !ldb_request_get_control(req, LDB_CONTROL_REVEAL_INTERNALS)) {
     407             :                                         /* we show these with REVEAL
     408             :                                            to allow dbcheck to find and
     409             :                                            cleanup these orphaned links */
     410             :                                         /* we won't keep this one, so not incrementing k */
     411        5898 :                                         continue;
     412             :                                 }
     413             :                         }
     414             :                         
     415    12200780 :                         if (make_extended_dn) {
     416     8456603 :                                 if (!ldb_dn_validate(dsdb_dn->dn)) {
     417           0 :                                         ldb_asprintf_errstring(ldb, 
     418             :                                                                "could not parse %.*s in %s on %s as a %s DN", 
     419           0 :                                                                (int)plain_dn->length, plain_dn->data,
     420           0 :                                                                msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
     421           0 :                                                                attribute->syntax->ldap_oid);
     422           0 :                                         talloc_free(dsdb_dn);
     423           0 :                                         return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_INVALID_DN_SYNTAX);
     424             :                                 }
     425             :                                 /* don't let users see the internal extended
     426             :                                    GUID components */
     427     8456603 :                                 if (!have_reveal_control) {
     428     8456603 :                                         const char *accept[] = { "GUID", "SID", NULL };
     429     8456603 :                                         ldb_dn_extended_filter(dn, accept);
     430             :                                 }
     431     8456603 :                                 dn_str = dsdb_dn_get_extended_linearized(msg->elements[i].values,
     432             :                                                                          dsdb_dn, ac->extended_type);
     433             :                         } else {
     434     3744177 :                                 dn_str = dsdb_dn_get_linearized(msg->elements[i].values,
     435             :                                                                 dsdb_dn);
     436             :                         }
     437             : 
     438    12200780 :                         if (!dn_str) {
     439           0 :                                 ldb_oom(ldb);
     440           0 :                                 talloc_free(dsdb_dn);
     441           0 :                                 return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
     442             :                         }
     443    12200780 :                         msg->elements[i].values[k] = data_blob_string_const(dn_str);
     444    12200780 :                         talloc_free(dsdb_dn);
     445    12200780 :                         k++;
     446             :                 }
     447             : 
     448     8030636 :                 if (k == 0) {
     449             :                         /* we've deleted all of the values from this
     450             :                          * element - remove the element */
     451         535 :                         ldb_msg_remove_element(msg, &msg->elements[i]);
     452         535 :                         i--;
     453             :                 } else {
     454     8030101 :                         msg->elements[i].num_values = k;
     455             :                 }
     456             :         }
     457    58498857 :         return ldb_module_send_entry(ac->req, msg, ares->controls);
     458             : }
     459             : 
     460    89369262 : static int extended_callback_ldb(struct ldb_request *req, struct ldb_reply *ares)
     461             : {
     462    89369262 :         return extended_callback(req, ares);
     463             : }
     464             : 
     465    30352211 : static int extended_dn_out_search(struct ldb_module *module, struct ldb_request *req,
     466             :                 int (*callback)(struct ldb_request *req, struct ldb_reply *ares))
     467             : {
     468             :         struct ldb_control *control;
     469             :         struct ldb_control *storage_format_control;
     470    30352211 :         struct ldb_extended_dn_control *extended_ctrl = NULL;
     471             :         struct extended_search_context *ac;
     472             :         struct ldb_request *down_req;
     473             :         char **new_attrs;
     474             :         const char * const *const_attrs;
     475    30352211 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
     476             :         int ret;
     477             : 
     478    30352211 :         struct extended_dn_out_private *p = talloc_get_type(ldb_module_get_private(module), struct extended_dn_out_private);
     479             : 
     480             :         /* The schema manipulation does not apply to special DNs */
     481    30352211 :         if (ldb_dn_is_special(req->op.search.base)) {
     482     5537030 :                 return ldb_next_request(module, req);
     483             :         }
     484             : 
     485             :         /* check if there's an extended dn control */
     486    24815181 :         control = ldb_request_get_control(req, LDB_CONTROL_EXTENDED_DN_OID);
     487    24815181 :         if (control && control->data) {
     488     9842534 :                 extended_ctrl = talloc_get_type(control->data, struct ldb_extended_dn_control);
     489     9842534 :                 if (!extended_ctrl) {
     490           0 :                         return LDB_ERR_PROTOCOL_ERROR;
     491             :                 }
     492             :         }
     493             : 
     494             :         /* Look to see if, as we are in 'store DN+GUID+SID' mode, the
     495             :          * client is after the storage format (to fill in linked
     496             :          * attributes) */
     497    24815181 :         storage_format_control = ldb_request_get_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID);
     498    24815181 :         if (!control && storage_format_control && storage_format_control->data) {
     499           0 :                 extended_ctrl = talloc_get_type(storage_format_control->data, struct ldb_extended_dn_control);
     500           0 :                 if (!extended_ctrl) {
     501           0 :                         ldb_set_errstring(ldb, "extended_dn_out: extended_ctrl was of the wrong data type");
     502           0 :                         return LDB_ERR_PROTOCOL_ERROR;
     503             :                 }
     504             :         }
     505             : 
     506    24815181 :         ac = talloc_zero(req, struct extended_search_context);
     507    24815181 :         if (ac == NULL) {
     508           0 :                 return ldb_oom(ldb);
     509             :         }
     510             : 
     511    24815181 :         ac->module = module;
     512    24815181 :         ac->schema = dsdb_get_schema(ldb, ac);
     513    24815181 :         ac->req = req;
     514    24815181 :         ac->inject = false;
     515    24815181 :         ac->remove_guid = false;
     516    24815181 :         ac->remove_sid = false;
     517             :         
     518    24815181 :         const_attrs = req->op.search.attrs;
     519             : 
     520             :         /* We only need to do special processing if we were asked for
     521             :          * the extended DN, or we are 'store DN+GUID+SID'
     522             :          * (!dereference) mode.  (This is the normal mode for LDB on
     523             :          * tdb). */
     524    24815181 :         if (control || (storage_format_control && p)) {
     525    11258428 :                 ac->inject = true;
     526    11258428 :                 if (extended_ctrl) {
     527     9842534 :                         ac->extended_type = extended_ctrl->type;
     528             :                 } else {
     529     1415894 :                         ac->extended_type = 0;
     530             :                 }
     531             : 
     532             :                 /* check if attrs only is specified, in that case check whether we need to modify them */
     533    11258428 :                 if (req->op.search.attrs && !is_attr_in_list(req->op.search.attrs, "*")) {
     534     9730692 :                         if (! is_attr_in_list(req->op.search.attrs, "objectGUID")) {
     535     8754231 :                                 ac->remove_guid = true;
     536             :                         }
     537     9730692 :                         if (! is_attr_in_list(req->op.search.attrs, "objectSid")) {
     538     9361602 :                                 ac->remove_sid = true;
     539             :                         }
     540     9730692 :                         if (ac->remove_guid || ac->remove_sid) {
     541     9490190 :                                 new_attrs = copy_attrs(ac, req->op.search.attrs);
     542     9490190 :                                 if (new_attrs == NULL) {
     543           0 :                                         return ldb_oom(ldb);
     544             :                                 }
     545             : 
     546     9490190 :                                 if (ac->remove_guid) {
     547     8754231 :                                         if (!add_attrs(ac, &new_attrs, "objectGUID"))
     548           0 :                                                 return ldb_operr(ldb);
     549             :                                 }
     550     9490190 :                                 if (ac->remove_sid) {
     551     9361602 :                                         if (!add_attrs(ac, &new_attrs, "objectSid"))
     552           0 :                                                 return ldb_operr(ldb);
     553             :                                 }
     554     9490190 :                                 const_attrs = (const char * const *)new_attrs;
     555             :                         }
     556             :                 }
     557             :         }
     558             : 
     559    24815181 :         ret = ldb_build_search_req_ex(&down_req,
     560             :                                       ldb, ac,
     561             :                                       req->op.search.base,
     562             :                                       req->op.search.scope,
     563             :                                       req->op.search.tree,
     564             :                                       const_attrs,
     565             :                                       req->controls,
     566             :                                       ac, callback,
     567             :                                       req);
     568    24815181 :         LDB_REQ_SET_LOCATION(down_req);
     569    24815181 :         if (ret != LDB_SUCCESS) {
     570           0 :                 return ret;
     571             :         }
     572             : 
     573             :         /* mark extended DN and storage format controls as done */
     574    24815181 :         if (control) {
     575    10381158 :                 control->critical = 0;
     576             :         }
     577             : 
     578    24815181 :         if (storage_format_control) {
     579     1297694 :                 storage_format_control->critical = 0;
     580             :         }
     581             : 
     582             :         /* perform the search */
     583    24815181 :         return ldb_next_request(module, down_req);
     584             : }
     585             : 
     586    30352211 : static int extended_dn_out_ldb_search(struct ldb_module *module, struct ldb_request *req)
     587             : {
     588    30352211 :         return extended_dn_out_search(module, req, extended_callback_ldb);
     589             : }
     590             : 
     591      132890 : static int extended_dn_out_ldb_init(struct ldb_module *module)
     592             : {
     593             :         int ret;
     594             : 
     595      132890 :         struct extended_dn_out_private *p = talloc(module, struct extended_dn_out_private);
     596             :         struct dsdb_extended_dn_store_format *dn_format;
     597             : 
     598      132890 :         ldb_module_set_private(module, p);
     599             : 
     600      132890 :         if (!p) {
     601           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     602             :         }
     603             : 
     604      132890 :         dn_format = talloc(p, struct dsdb_extended_dn_store_format);
     605      132890 :         if (!dn_format) {
     606           0 :                 talloc_free(p);
     607           0 :                 return ldb_oom(ldb_module_get_ctx(module));
     608             :         }
     609             : 
     610      132890 :         dn_format->store_extended_dn_in_ldb = true;
     611      132890 :         ret = ldb_set_opaque(ldb_module_get_ctx(module), DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME, dn_format);
     612      132890 :         if (ret != LDB_SUCCESS) {
     613           0 :                 talloc_free(p);
     614           0 :                 return ret;
     615             :         }
     616             : 
     617      132890 :         p->dereference = false;
     618      132890 :         p->normalise = false;
     619             : 
     620      132890 :         ret = ldb_mod_register_control(module, LDB_CONTROL_EXTENDED_DN_OID);
     621      132890 :         if (ret != LDB_SUCCESS) {
     622           0 :                 ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
     623             :                         "extended_dn_out: Unable to register control with rootdse!\n");
     624           0 :                 return ldb_operr(ldb_module_get_ctx(module));
     625             :         }
     626             : 
     627      132890 :         return ldb_next_init(module);
     628             : }
     629             : 
     630             : static const struct ldb_module_ops ldb_extended_dn_out_ldb_module_ops = {
     631             :         .name              = "extended_dn_out_ldb",
     632             :         .search            = extended_dn_out_ldb_search,
     633             :         .init_context      = extended_dn_out_ldb_init,
     634             : };
     635             : 
     636             : /*
     637             :   initialise the module
     638             :  */
     639        5536 : _PUBLIC_ int ldb_extended_dn_out_module_init(const char *version)
     640             : {
     641             :         int ret;
     642        5536 :         LDB_MODULE_CHECK_VERSION(version);
     643        5536 :         ret = ldb_register_module(&ldb_extended_dn_out_ldb_module_ops);
     644        5536 :         if (ret != LDB_SUCCESS) {
     645           0 :                 return ret;
     646             :         }
     647        5536 :         return LDB_SUCCESS;
     648             : }

Generated by: LCOV version 1.13