LCOV - code coverage report
Current view: top level - source3/winbindd - idmap_autorid_tdb.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 0 506 0.0 %
Date: 2024-06-13 04:01:37 Functions: 0 32 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  idmap_autorid_tdb: This file contains common code used by
       3             :  *  idmap_autorid and net idmap autorid utilities. The common
       4             :  *  code provides functions for performing various operations
       5             :  *  on autorid.tdb
       6             :  *
       7             :  *  Copyright (C) Christian Ambach, 2010-2012
       8             :  *  Copyright (C) Atul Kulkarni, 2013
       9             :  *  Copyright (C) Michael Adam, 2012-2013
      10             :  *
      11             :  *  This program is free software; you can redistribute it and/or modify
      12             :  *  it under the terms of the GNU General Public License as published by
      13             :  *  the Free Software Foundation; either version 3 of the License, or
      14             :  *  (at your option) any later version.
      15             :  *
      16             :  *  This program 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
      19             :  *  GNU General Public License for more details.
      20             :  *
      21             :  *  You should have received a copy of the GNU General Public License
      22             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      23             :  *
      24             :  */
      25             : 
      26             : #include "idmap_autorid_tdb.h"
      27             : #include "../libcli/security/dom_sid.h"
      28             : #include "lib/util/string_wrappers.h"
      29             : 
      30             : /**
      31             :  * Build the database keystring for getting a range
      32             :  * belonging to a domain sid and a range index.
      33             :  */
      34           0 : static void idmap_autorid_build_keystr(const char *domsid,
      35             :                                        uint32_t domain_range_index,
      36             :                                        fstring keystr)
      37             : {
      38           0 :         if (domain_range_index > 0) {
      39           0 :                 fstr_sprintf(keystr, "%s#%"PRIu32,
      40             :                              domsid, domain_range_index);
      41             :         } else {
      42           0 :                 fstrcpy(keystr, domsid);
      43             :         }
      44           0 : }
      45             : 
      46           0 : static char *idmap_autorid_build_keystr_talloc(TALLOC_CTX *mem_ctx,
      47             :                                               const char *domsid,
      48             :                                               uint32_t domain_range_index)
      49             : {
      50             :         char *keystr;
      51             : 
      52           0 :         if (domain_range_index > 0) {
      53           0 :                 keystr = talloc_asprintf(mem_ctx, "%s#%"PRIu32, domsid,
      54             :                                          domain_range_index);
      55             :         } else {
      56           0 :                 keystr = talloc_strdup(mem_ctx, domsid);
      57             :         }
      58             : 
      59           0 :         return keystr;
      60             : }
      61             : 
      62             : 
      63           0 : static bool idmap_autorid_validate_sid(const char *sid)
      64             : {
      65             :         struct dom_sid ignore;
      66           0 :         if (sid == NULL) {
      67           0 :                 return false;
      68             :         }
      69             : 
      70           0 :         if (strcmp(sid, ALLOC_RANGE) == 0) {
      71           0 :                 return true;
      72             :         }
      73             : 
      74           0 :         return dom_sid_parse(sid, &ignore);
      75             : }
      76             : 
      77             : struct idmap_autorid_addrange_ctx {
      78             :         struct autorid_range_config *range;
      79             :         bool acquire;
      80             : };
      81             : 
      82           0 : static NTSTATUS idmap_autorid_addrange_action(struct db_context *db,
      83             :                                               void *private_data)
      84             : {
      85             :         struct idmap_autorid_addrange_ctx *ctx;
      86             :         uint32_t requested_rangenum, stored_rangenum;
      87             :         struct autorid_range_config *range;
      88             :         bool acquire;
      89             :         NTSTATUS ret;
      90             :         uint32_t hwm;
      91             :         char *numstr;
      92           0 :         struct autorid_global_config globalcfg = {0};
      93             :         fstring keystr;
      94             :         uint32_t increment;
      95           0 :         TALLOC_CTX *mem_ctx = NULL;
      96             : 
      97           0 :         ctx = (struct idmap_autorid_addrange_ctx *)private_data;
      98           0 :         range = ctx->range;
      99           0 :         acquire = ctx->acquire;
     100           0 :         requested_rangenum = range->rangenum;
     101             : 
     102           0 :         if (db == NULL) {
     103           0 :                 DEBUG(3, ("Invalid database argument: NULL"));
     104           0 :                 return NT_STATUS_INVALID_PARAMETER;
     105             :         }
     106             : 
     107           0 :         if (range == NULL) {
     108           0 :                 DEBUG(3, ("Invalid range argument: NULL"));
     109           0 :                 return NT_STATUS_INVALID_PARAMETER;
     110             :         }
     111             : 
     112           0 :         DEBUG(10, ("Adding new range for domain %s "
     113             :                    "(domain_range_index=%"PRIu32")\n",
     114             :                    range->domsid, range->domain_range_index));
     115             : 
     116           0 :         if (!idmap_autorid_validate_sid(range->domsid)) {
     117           0 :                 DEBUG(3, ("Invalid SID: %s\n", range->domsid));
     118           0 :                 return NT_STATUS_INVALID_PARAMETER;
     119             :         }
     120             : 
     121           0 :         idmap_autorid_build_keystr(range->domsid, range->domain_range_index,
     122             :                                    keystr);
     123             : 
     124           0 :         ret = dbwrap_fetch_uint32_bystring(db, keystr, &stored_rangenum);
     125             : 
     126           0 :         if (NT_STATUS_IS_OK(ret)) {
     127             :                 /* entry is already present*/
     128           0 :                 if (acquire) {
     129           0 :                         DEBUG(10, ("domain range already allocated - "
     130             :                                    "Not adding!\n"));
     131             : 
     132           0 :                         ret = idmap_autorid_loadconfig(db, &globalcfg);
     133           0 :                         if (!NT_STATUS_IS_OK(ret)) {
     134           0 :                                 DEBUG(1, ("Fatal error while fetching "
     135             :                                           "configuration: %s\n",
     136             :                                           nt_errstr(ret)));
     137           0 :                                 goto error;
     138             :                         }
     139             : 
     140           0 :                         range->rangenum = stored_rangenum;
     141           0 :                         range->low_id = globalcfg.minvalue
     142           0 :                                 + range->rangenum * globalcfg.rangesize;
     143           0 :                         range->high_id =
     144           0 :                                 range->low_id  + globalcfg.rangesize - 1;
     145             : 
     146           0 :                         return NT_STATUS_OK;
     147             :                 }
     148             : 
     149           0 :                 if (stored_rangenum != requested_rangenum) {
     150           0 :                         DEBUG(1, ("Error: requested rangenumber (%u) differs "
     151             :                                   "from stored one (%u).\n",
     152             :                                   requested_rangenum, stored_rangenum));
     153           0 :                         return NT_STATUS_UNSUCCESSFUL;
     154             :                 }
     155             : 
     156           0 :                 DEBUG(10, ("Note: stored range agrees with requested "
     157             :                            "one - ok\n"));
     158           0 :                 return NT_STATUS_OK;
     159             :         }
     160             : 
     161             :         /* fetch the current HWM */
     162           0 :         ret = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
     163           0 :         if (!NT_STATUS_IS_OK(ret)) {
     164           0 :                 DEBUG(1, ("Fatal error while fetching current "
     165             :                           "HWM value: %s\n", nt_errstr(ret)));
     166           0 :                 return NT_STATUS_INTERNAL_ERROR;
     167             :         }
     168             : 
     169           0 :         mem_ctx = talloc_stackframe();
     170             : 
     171           0 :         ret = idmap_autorid_loadconfig(db, &globalcfg);
     172           0 :         if (!NT_STATUS_IS_OK(ret)) {
     173           0 :                 DEBUG(1, ("Fatal error while fetching configuration: %s\n",
     174             :                           nt_errstr(ret)));
     175           0 :                 goto error;
     176             :         }
     177             : 
     178           0 :         if (acquire) {
     179             :                 /*
     180             :                  * automatically acquire the next range
     181             :                  */
     182           0 :                 requested_rangenum = hwm;
     183             :         }
     184             : 
     185           0 :         if (requested_rangenum >= globalcfg.maxranges) {
     186           0 :                 DEBUG(1, ("Not enough ranges available: New range %u must be "
     187             :                           "smaller than configured maximum number of ranges "
     188             :                           "(%u).\n",
     189             :                           requested_rangenum, globalcfg.maxranges));
     190           0 :                 ret = NT_STATUS_NO_MEMORY;
     191           0 :                 goto error;
     192             :         }
     193             : 
     194             :         /*
     195             :          * Check that it is not yet taken.
     196             :          * If the range is requested and < HWM, we need
     197             :          * to check anyways, and otherwise, we also better
     198             :          * check in order to prevent further corruption
     199             :          * in case the db has been externally modified.
     200             :          */
     201             : 
     202           0 :         numstr = talloc_asprintf(mem_ctx, "%u", requested_rangenum);
     203           0 :         if (!numstr) {
     204           0 :                 DEBUG(1, ("Talloc failed!\n"));
     205           0 :                 ret = NT_STATUS_NO_MEMORY;
     206           0 :                 goto error;
     207             :         }
     208             : 
     209           0 :         if (dbwrap_exists(db, string_term_tdb_data(numstr))) {
     210           0 :                 DEBUG(1, ("Requested range '%s' is already in use.\n", numstr));
     211             : 
     212           0 :                 if (requested_rangenum < hwm) {
     213           0 :                         ret = NT_STATUS_INVALID_PARAMETER;
     214             :                 } else {
     215           0 :                         ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
     216             :                 }
     217             : 
     218           0 :                 goto error;
     219             :         }
     220             : 
     221           0 :         if (requested_rangenum >= hwm) {
     222             :                 /*
     223             :                  * requested or automatic range >= HWM:
     224             :                  * increment the HWM.
     225             :                  */
     226             : 
     227             :                 /* HWM always contains current max range + 1 */
     228           0 :                 increment = requested_rangenum + 1 - hwm;
     229             : 
     230             :                 /* increase the HWM */
     231           0 :                 ret = dbwrap_change_uint32_atomic_bystring(db, HWM, &hwm,
     232             :                                                            increment);
     233           0 :                 if (!NT_STATUS_IS_OK(ret)) {
     234           0 :                         DEBUG(1, ("Fatal error while incrementing the HWM "
     235             :                                   "value in the database: %s\n",
     236             :                                   nt_errstr(ret)));
     237           0 :                         goto error;
     238             :                 }
     239             :         }
     240             : 
     241             :         /*
     242             :          * store away the new mapping in both directions
     243             :          */
     244             : 
     245           0 :         ret = dbwrap_store_uint32_bystring(db, keystr, requested_rangenum);
     246           0 :         if (!NT_STATUS_IS_OK(ret)) {
     247           0 :                 DEBUG(1, ("Fatal error while storing new "
     248             :                           "domain->range assignment: %s\n", nt_errstr(ret)));
     249           0 :                 goto error;
     250             :         }
     251             : 
     252           0 :         numstr = talloc_asprintf(mem_ctx, "%u", requested_rangenum);
     253           0 :         if (!numstr) {
     254           0 :                 ret = NT_STATUS_NO_MEMORY;
     255           0 :                 goto error;
     256             :         }
     257             : 
     258           0 :         ret = dbwrap_store_bystring(db, numstr,
     259             :                         string_term_tdb_data(keystr), TDB_INSERT);
     260             : 
     261           0 :         if (!NT_STATUS_IS_OK(ret)) {
     262           0 :                 DEBUG(1, ("Fatal error while storing new "
     263             :                           "domain->range assignment: %s\n", nt_errstr(ret)));
     264           0 :                 goto error;
     265             :         }
     266             : 
     267           0 :         DEBUG(5, ("%s new range #%d for domain %s "
     268             :                   "(domain_range_index=%"PRIu32")\n",
     269             :                   (acquire?"Acquired":"Stored"),
     270             :                   requested_rangenum, keystr,
     271             :                   range->domain_range_index));
     272             : 
     273           0 :         range->rangenum = requested_rangenum;
     274             : 
     275           0 :         range->low_id = globalcfg.minvalue
     276           0 :                       + range->rangenum * globalcfg.rangesize;
     277           0 :         range->high_id = range->low_id  + globalcfg.rangesize - 1;
     278             : 
     279           0 :         ret = NT_STATUS_OK;
     280             : 
     281           0 : error:
     282           0 :         talloc_free(mem_ctx);
     283           0 :         return ret;
     284             : }
     285             : 
     286           0 : static NTSTATUS idmap_autorid_addrange(struct db_context *db,
     287             :                                        struct autorid_range_config *range,
     288             :                                        bool acquire)
     289             : {
     290             :         NTSTATUS status;
     291             :         struct idmap_autorid_addrange_ctx ctx;
     292             : 
     293           0 :         ctx.acquire = acquire;
     294           0 :         ctx.range = range;
     295             : 
     296           0 :         status = dbwrap_trans_do(db, idmap_autorid_addrange_action, &ctx);
     297           0 :         return status;
     298             : }
     299             : 
     300           0 : NTSTATUS idmap_autorid_setrange(struct db_context *db,
     301             :                                 const char *domsid,
     302             :                                 uint32_t domain_range_index,
     303             :                                 uint32_t rangenum)
     304             : {
     305             :         NTSTATUS status;
     306             :         struct autorid_range_config range;
     307             : 
     308           0 :         ZERO_STRUCT(range);
     309           0 :         fstrcpy(range.domsid, domsid);
     310           0 :         range.domain_range_index = domain_range_index;
     311           0 :         range.rangenum = rangenum;
     312             : 
     313           0 :         status = idmap_autorid_addrange(db, &range, false);
     314           0 :         return status;
     315             : }
     316             : 
     317           0 : NTSTATUS idmap_autorid_acquire_range(struct db_context *db,
     318             :                                      struct autorid_range_config *range)
     319             : {
     320           0 :         return idmap_autorid_addrange(db, range, true);
     321             : }
     322             : 
     323           0 : static NTSTATUS idmap_autorid_getrange_int(struct db_context *db,
     324             :                                            struct autorid_range_config *range)
     325             : {
     326           0 :         NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
     327           0 :         struct autorid_global_config globalcfg = {0};
     328             :         fstring keystr;
     329             : 
     330           0 :         if (db == NULL || range == NULL) {
     331           0 :                 DEBUG(3, ("Invalid arguments received\n"));
     332           0 :                 goto done;
     333             :         }
     334             : 
     335           0 :         if (!idmap_autorid_validate_sid(range->domsid)) {
     336           0 :                 DEBUG(3, ("Invalid SID: '%s'\n", range->domsid));
     337           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     338           0 :                 goto done;
     339             :         }
     340             : 
     341           0 :         idmap_autorid_build_keystr(range->domsid, range->domain_range_index,
     342             :                                    keystr);
     343             : 
     344           0 :         DEBUG(10, ("reading domain range for key %s\n", keystr));
     345           0 :         status = dbwrap_fetch_uint32_bystring(db, keystr, &(range->rangenum));
     346           0 :         if (!NT_STATUS_IS_OK(status)) {
     347           0 :                 DEBUG(1, ("Failed to read database record for key '%s': %s\n",
     348             :                           keystr, nt_errstr(status)));
     349           0 :                 goto done;
     350             :         }
     351             : 
     352           0 :         status = idmap_autorid_loadconfig(db, &globalcfg);
     353           0 :         if (!NT_STATUS_IS_OK(status)) {
     354           0 :                 DEBUG(1, ("Failed to read global configuration"));
     355           0 :                 goto done;
     356             :         }
     357           0 :         range->low_id = globalcfg.minvalue
     358           0 :                       + range->rangenum * globalcfg.rangesize;
     359           0 :         range->high_id = range->low_id  + globalcfg.rangesize - 1;
     360           0 : done:
     361           0 :         return status;
     362             : }
     363             : 
     364           0 : NTSTATUS idmap_autorid_getrange(struct db_context *db,
     365             :                                 const char *domsid,
     366             :                                 uint32_t domain_range_index,
     367             :                                 uint32_t *rangenum,
     368             :                                 uint32_t *low_id)
     369             : {
     370             :         NTSTATUS status;
     371             :         struct autorid_range_config range;
     372             : 
     373           0 :         if (rangenum == NULL) {
     374           0 :                 return NT_STATUS_INVALID_PARAMETER;
     375             :         }
     376             : 
     377           0 :         ZERO_STRUCT(range);
     378           0 :         fstrcpy(range.domsid, domsid);
     379           0 :         range.domain_range_index = domain_range_index;
     380             : 
     381           0 :         status = idmap_autorid_getrange_int(db, &range);
     382           0 :         if (!NT_STATUS_IS_OK(status)) {
     383           0 :                 return status;
     384             :         }
     385             : 
     386           0 :         *rangenum = range.rangenum;
     387             : 
     388           0 :         if (low_id != NULL) {
     389           0 :                 *low_id = range.low_id;
     390             :         }
     391             : 
     392           0 :         return NT_STATUS_OK;
     393             : }
     394             : 
     395           0 : NTSTATUS idmap_autorid_get_domainrange(struct db_context *db,
     396             :                                        struct autorid_range_config *range,
     397             :                                        bool read_only)
     398             : {
     399             :         NTSTATUS ret;
     400             : 
     401           0 :         ret = idmap_autorid_getrange_int(db, range);
     402           0 :         if (!NT_STATUS_IS_OK(ret)) {
     403           0 :                 DEBUG(10, ("Failed to read range config for '%s': %s\n",
     404             :                            range->domsid, nt_errstr(ret)));
     405           0 :                 if (read_only) {
     406           0 :                         DEBUG(10, ("Not allocating new range for '%s' because "
     407             :                                    "read-only is enabled.\n", range->domsid));
     408           0 :                         return NT_STATUS_NOT_FOUND;
     409             :                 }
     410             : 
     411           0 :                 ret = idmap_autorid_acquire_range(db, range);
     412             :         }
     413             : 
     414           0 :         DEBUG(10, ("Using range #%d for domain %s "
     415             :                    "(domain_range_index=%"PRIu32", low_id=%"PRIu32")\n",
     416             :                    range->rangenum, range->domsid, range->domain_range_index,
     417             :                    range->low_id));
     418             : 
     419           0 :         return ret;
     420             : }
     421             : 
     422             : /* initialize the given HWM to 0 if it does not exist yet */
     423           0 : static NTSTATUS idmap_autorid_init_hwm_action(struct db_context *db,
     424             :                                               void *private_data)
     425             : {
     426             :         NTSTATUS status;
     427             :         uint32_t hwmval;
     428             :         const char *hwm;
     429             : 
     430           0 :         hwm = (char *)private_data;
     431             : 
     432           0 :         status = dbwrap_fetch_uint32_bystring(db, hwm, &hwmval);
     433           0 :         if (NT_STATUS_IS_OK(status)) {
     434           0 :                 DEBUG(1, ("HWM (%s) already initialized in autorid database "
     435             :                           "(value %"PRIu32").\n", hwm, hwmval));
     436           0 :                 return NT_STATUS_OK;
     437             :         }
     438           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     439           0 :                 DEBUG(0, ("Error fetching HWM (%s) from autorid "
     440             :                           "database: %s\n", hwm, nt_errstr(status)));
     441           0 :                 return status;
     442             :         }
     443             : 
     444           0 :         status = dbwrap_trans_store_uint32_bystring(db, hwm, 0);
     445           0 :         if (!NT_STATUS_IS_OK(status)) {
     446           0 :                 DEBUG(0, ("Error storing HWM (%s) in autorid database: %s\n",
     447             :                           hwm, nt_errstr(status)));
     448           0 :                 return status;
     449             :         }
     450             : 
     451           0 :         return NT_STATUS_OK;
     452             : }
     453             : 
     454           0 : NTSTATUS idmap_autorid_init_hwm(struct db_context *db, const char *hwm)
     455             : {
     456             :         NTSTATUS status;
     457             :         uint32_t hwmval;
     458             : 
     459           0 :         status = dbwrap_fetch_uint32_bystring(db, hwm, &hwmval);
     460           0 :         if (NT_STATUS_IS_OK(status)) {
     461           0 :                 DEBUG(1, ("HWM (%s) already initialized in autorid database "
     462             :                           "(value %"PRIu32").\n", hwm, hwmval));
     463           0 :                 return NT_STATUS_OK;
     464             :         }
     465           0 :         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     466           0 :                 DEBUG(0, ("unable to fetch HWM (%s) from autorid "
     467             :                           "database: %s\n", hwm,  nt_errstr(status)));
     468           0 :                 return status;
     469             :         }
     470             : 
     471           0 :         status = dbwrap_trans_do(db, idmap_autorid_init_hwm_action,
     472             :                                  discard_const(hwm));
     473           0 :         if (!NT_STATUS_IS_OK(status)) {
     474           0 :                 DEBUG(0, ("Error initializing HWM (%s) in autorid database: "
     475             :                           "%s\n", hwm, nt_errstr(status)));
     476           0 :                 return NT_STATUS_INTERNAL_DB_ERROR;
     477             :         }
     478             : 
     479           0 :         DEBUG(1, ("Initialized HWM (%s) in autorid database.\n", hwm));
     480             : 
     481           0 :         return NT_STATUS_OK;
     482             : }
     483             : 
     484             : /*
     485             :  * Delete a domain#index <-> range mapping from the database.
     486             :  * The mapping is specified by the sid and index.
     487             :  * If force == true, invalid mapping records are deleted as far
     488             :  * as possible, otherwise they are left untouched.
     489             :  */
     490             : 
     491             : struct idmap_autorid_delete_range_by_sid_ctx {
     492             :         const char *domsid;
     493             :         uint32_t domain_range_index;
     494             :         bool force;
     495             : };
     496             : 
     497           0 : static NTSTATUS idmap_autorid_delete_range_by_sid_action(struct db_context *db,
     498             :                                                          void *private_data)
     499             : {
     500           0 :         struct idmap_autorid_delete_range_by_sid_ctx *ctx =
     501             :                 (struct idmap_autorid_delete_range_by_sid_ctx *)private_data;
     502             :         const char *domsid;
     503             :         uint32_t domain_range_index;
     504             :         uint32_t rangenum;
     505             :         char *keystr;
     506             :         char *range_keystr;
     507             :         TDB_DATA data;
     508             :         NTSTATUS status;
     509           0 :         TALLOC_CTX *frame = talloc_stackframe();
     510           0 :         bool is_valid_range_mapping = true;
     511             :         bool force;
     512             : 
     513           0 :         domsid = ctx->domsid;
     514           0 :         domain_range_index = ctx->domain_range_index;
     515           0 :         force = ctx->force;
     516             : 
     517           0 :         keystr = idmap_autorid_build_keystr_talloc(frame, domsid,
     518             :                                                    domain_range_index);
     519           0 :         if (keystr == NULL) {
     520           0 :                 status = NT_STATUS_NO_MEMORY;
     521           0 :                 goto done;
     522             :         }
     523             : 
     524           0 :         status = dbwrap_fetch_uint32_bystring(db, keystr, &rangenum);
     525           0 :         if (!NT_STATUS_IS_OK(status)) {
     526           0 :                 goto done;
     527             :         }
     528             : 
     529           0 :         range_keystr = talloc_asprintf(frame, "%"PRIu32, rangenum);
     530           0 :         if (range_keystr == NULL) {
     531           0 :                 status = NT_STATUS_NO_MEMORY;
     532           0 :                 goto done;
     533             :         }
     534             : 
     535           0 :         status = dbwrap_fetch_bystring(db, frame, range_keystr, &data);
     536           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     537           0 :                 DEBUG(1, ("Incomplete mapping %s -> %s: no backward mapping\n",
     538             :                           keystr, range_keystr));
     539           0 :                 is_valid_range_mapping = false;
     540           0 :         } else if (!NT_STATUS_IS_OK(status)) {
     541           0 :                 DEBUG(1, ("Error fetching reverse mapping for %s -> %s:  %s\n",
     542             :                           keystr, range_keystr, nt_errstr(status)));
     543           0 :                 goto done;
     544           0 :         } else if (strncmp((const char *)data.dptr, keystr, strlen(keystr))
     545             :                    != 0)
     546             :         {
     547           0 :                 DEBUG(1, ("Invalid mapping: %s -> %s -> %s\n",
     548             :                           keystr, range_keystr, (const char *)data.dptr));
     549           0 :                 is_valid_range_mapping = false;
     550             :         }
     551             : 
     552           0 :         if (!is_valid_range_mapping && !force) {
     553           0 :                 DEBUG(10, ("Not deleting invalid mapping, since not in force "
     554             :                            "mode.\n"));
     555           0 :                 status = NT_STATUS_FILE_INVALID;
     556           0 :                 goto done;
     557             :         }
     558             : 
     559           0 :         status = dbwrap_delete_bystring(db, keystr);
     560           0 :         if (!NT_STATUS_IS_OK(status)) {
     561           0 :                 DEBUG(1, ("Deletion of '%s' failed: %s\n",
     562             :                           keystr, nt_errstr(status)));
     563           0 :                 goto done;
     564             :         }
     565             : 
     566           0 :         if (!is_valid_range_mapping) {
     567           0 :                 goto done;
     568             :         }
     569             : 
     570           0 :         status = dbwrap_delete_bystring(db, range_keystr);
     571           0 :         if (!NT_STATUS_IS_OK(status)) {
     572           0 :                 DEBUG(1, ("Deletion of '%s' failed: %s\n",
     573             :                           range_keystr, nt_errstr(status)));
     574           0 :                 goto done;
     575             :         }
     576             : 
     577           0 :         DEBUG(10, ("Deleted range mapping %s <--> %s\n", keystr,
     578             :                    range_keystr));
     579             : 
     580           0 : done:
     581           0 :         TALLOC_FREE(frame);
     582           0 :         return status;
     583             : }
     584             : 
     585           0 : NTSTATUS idmap_autorid_delete_range_by_sid(struct db_context *db,
     586             :                                            const char *domsid,
     587             :                                            uint32_t domain_range_index,
     588             :                                            bool force)
     589             : {
     590             :         NTSTATUS status;
     591             :         struct idmap_autorid_delete_range_by_sid_ctx ctx;
     592             : 
     593           0 :         ctx.domain_range_index = domain_range_index;
     594           0 :         ctx.domsid = domsid;
     595           0 :         ctx.force = force;
     596             : 
     597           0 :         status = dbwrap_trans_do(db, idmap_autorid_delete_range_by_sid_action,
     598             :                                  &ctx);
     599           0 :         return status;
     600             : }
     601             : 
     602             : /*
     603             :  * Delete a domain#index <-> range mapping from the database.
     604             :  * The mapping is specified by the range number.
     605             :  * If force == true, invalid mapping records are deleted as far
     606             :  * as possible, otherwise they are left untouched.
     607             :  */
     608             : struct idmap_autorid_delete_range_by_num_ctx {
     609             :         uint32_t rangenum;
     610             :         bool force;
     611             : };
     612             : 
     613           0 : static NTSTATUS idmap_autorid_delete_range_by_num_action(struct db_context *db,
     614             :                                                            void *private_data)
     615             : {
     616           0 :         struct idmap_autorid_delete_range_by_num_ctx *ctx =
     617             :                 (struct idmap_autorid_delete_range_by_num_ctx *)private_data;
     618             :         uint32_t rangenum;
     619           0 :         char *keystr = NULL;
     620             :         char *range_keystr;
     621             :         TDB_DATA val;
     622             :         NTSTATUS status;
     623           0 :         TALLOC_CTX *frame = talloc_stackframe();
     624           0 :         bool is_valid_range_mapping = true;
     625             :         bool force;
     626             : 
     627           0 :         rangenum = ctx->rangenum;
     628           0 :         force = ctx->force;
     629             : 
     630           0 :         range_keystr = talloc_asprintf(frame, "%"PRIu32, rangenum);
     631           0 :         if (range_keystr == NULL) {
     632           0 :                 status = NT_STATUS_NO_MEMORY;
     633           0 :                 goto done;
     634             :         }
     635             : 
     636           0 :         ZERO_STRUCT(val);
     637             : 
     638           0 :         status = dbwrap_fetch_bystring(db, frame, range_keystr, &val);
     639           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     640           0 :                 DEBUG(10, ("Did not find range '%s' in database.\n",
     641             :                            range_keystr));
     642           0 :                 goto done;
     643           0 :         } else if (!NT_STATUS_IS_OK(status)) {
     644           0 :                 DEBUG(5, ("Error fetching rang key: %s\n", nt_errstr(status)));
     645           0 :                 goto done;
     646             :         }
     647             : 
     648           0 :         if (val.dptr == NULL) {
     649           0 :                 DEBUG(1, ("Invalid mapping: %s -> empty value\n",
     650             :                           range_keystr));
     651           0 :                 is_valid_range_mapping = false;
     652             :         } else {
     653           0 :                 uint32_t reverse_rangenum = 0;
     654             : 
     655           0 :                 keystr = (char *)val.dptr;
     656             : 
     657           0 :                 status = dbwrap_fetch_uint32_bystring(db, keystr,
     658             :                                                       &reverse_rangenum);
     659           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     660           0 :                         DEBUG(1, ("Incomplete mapping %s -> %s: "
     661             :                                   "no backward mapping\n",
     662             :                                   range_keystr, keystr));
     663           0 :                         is_valid_range_mapping = false;
     664           0 :                 } else if (!NT_STATUS_IS_OK(status)) {
     665           0 :                         DEBUG(1, ("Error fetching reverse mapping for "
     666             :                                   "%s -> %s: %s\n",
     667             :                                   range_keystr, keystr, nt_errstr(status)));
     668           0 :                         goto done;
     669           0 :                 } else if (rangenum != reverse_rangenum) {
     670           0 :                         is_valid_range_mapping = false;
     671             :                 }
     672             :         }
     673             : 
     674           0 :         if (!is_valid_range_mapping && !force) {
     675           0 :                 DEBUG(10, ("Not deleting invalid mapping, since not in force "
     676             :                            "mode.\n"));
     677           0 :                 status = NT_STATUS_FILE_INVALID;
     678           0 :                 goto done;
     679             :         }
     680             : 
     681           0 :         status = dbwrap_delete_bystring(db, range_keystr);
     682           0 :         if (!NT_STATUS_IS_OK(status)) {
     683           0 :                 DEBUG(1, ("Deletion of '%s' failed: %s\n",
     684             :                           range_keystr, nt_errstr(status)));
     685           0 :                 goto done;
     686             :         }
     687             : 
     688           0 :         if (!is_valid_range_mapping) {
     689           0 :                 goto done;
     690             :         }
     691             : 
     692           0 :         status = dbwrap_delete_bystring(db, keystr);
     693           0 :         if (!NT_STATUS_IS_OK(status)) {
     694           0 :                 DEBUG(1, ("Deletion of '%s' failed: %s\n",
     695             :                           keystr, nt_errstr(status)));
     696           0 :                 goto done;
     697             :         }
     698             : 
     699           0 :         DEBUG(10, ("Deleted range mapping %s <--> %s\n", range_keystr,
     700             :                    keystr));
     701             : 
     702           0 : done:
     703           0 :         talloc_free(frame);
     704           0 :         return status;
     705             : }
     706             : 
     707           0 : NTSTATUS idmap_autorid_delete_range_by_num(struct db_context *db,
     708             :                                            uint32_t rangenum,
     709             :                                            bool force)
     710             : {
     711             :         NTSTATUS status;
     712             :         struct idmap_autorid_delete_range_by_num_ctx ctx;
     713             : 
     714           0 :         ctx.rangenum = rangenum;
     715           0 :         ctx.force = force;
     716             : 
     717           0 :         status = dbwrap_trans_do(db, idmap_autorid_delete_range_by_num_action,
     718             :                                  &ctx);
     719           0 :         return status;
     720             : }
     721             : 
     722             : /**
     723             :  * Open and possibly create the database.
     724             :  */
     725           0 : NTSTATUS idmap_autorid_db_open(const char *path,
     726             :                                TALLOC_CTX *mem_ctx,
     727             :                                struct db_context **db)
     728             : {
     729           0 :         if (*db != NULL) {
     730             :                 /* its already open */
     731           0 :                 return NT_STATUS_OK;
     732             :         }
     733             : 
     734             :         /* Open idmap repository */
     735           0 :         *db = db_open(mem_ctx, path, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644,
     736             :                       DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
     737             : 
     738           0 :         if (*db == NULL) {
     739           0 :                 DEBUG(0, ("Unable to open idmap_autorid database '%s'\n", path));
     740           0 :                 return NT_STATUS_UNSUCCESSFUL;
     741             :         }
     742             : 
     743           0 :         return NT_STATUS_OK;
     744             : }
     745             : 
     746             : /**
     747             :  * Initialize the high watermark records in the database.
     748             :  */
     749           0 : NTSTATUS idmap_autorid_init_hwms(struct db_context *db)
     750             : {
     751             :         NTSTATUS status;
     752             : 
     753           0 :         status = idmap_autorid_init_hwm(db, HWM);
     754           0 :         if (!NT_STATUS_IS_OK(status)) {
     755           0 :                 return status;
     756             :         }
     757             : 
     758           0 :         status = idmap_autorid_init_hwm(db, ALLOC_HWM_UID);
     759           0 :         if (!NT_STATUS_IS_OK(status)) {
     760           0 :                 return status;
     761             :         }
     762             : 
     763           0 :         status = idmap_autorid_init_hwm(db, ALLOC_HWM_GID);
     764             : 
     765           0 :         return status;
     766             : }
     767             : 
     768           0 : NTSTATUS idmap_autorid_db_init(const char *path,
     769             :                                TALLOC_CTX *mem_ctx,
     770             :                                struct db_context **db)
     771             : {
     772             :         NTSTATUS status;
     773             : 
     774           0 :         status = idmap_autorid_db_open(path, mem_ctx, db);
     775           0 :         if (!NT_STATUS_IS_OK(status)) {
     776           0 :                 return status;
     777             :         }
     778             : 
     779           0 :         status = idmap_autorid_init_hwms(*db);
     780           0 :         return status;
     781             : }
     782             : 
     783             : 
     784             : 
     785             : struct idmap_autorid_fetch_config_state {
     786             :         TALLOC_CTX *mem_ctx;
     787             :         char *configstr;
     788             : };
     789             : 
     790           0 : static void idmap_autorid_config_parser(TDB_DATA key, TDB_DATA value,
     791             :                                         void *private_data)
     792             : {
     793             :         struct idmap_autorid_fetch_config_state *state;
     794             : 
     795           0 :         state = (struct idmap_autorid_fetch_config_state *)private_data;
     796             : 
     797             :         /*
     798             :          * strndup because we have non-nullterminated strings in the db
     799             :          */
     800           0 :         state->configstr = talloc_strndup(
     801           0 :                 state->mem_ctx, (const char *)value.dptr, value.dsize);
     802           0 : }
     803             : 
     804           0 : NTSTATUS idmap_autorid_getconfigstr(struct db_context *db, TALLOC_CTX *mem_ctx,
     805             :                                     char **result)
     806             : {
     807             :         TDB_DATA key;
     808             :         NTSTATUS status;
     809             :         struct idmap_autorid_fetch_config_state state;
     810             : 
     811           0 :         if (result == NULL) {
     812           0 :                 return NT_STATUS_INVALID_PARAMETER;
     813             :         }
     814             : 
     815           0 :         key = string_term_tdb_data(CONFIGKEY);
     816             : 
     817           0 :         state.mem_ctx = mem_ctx;
     818           0 :         state.configstr = NULL;
     819             : 
     820           0 :         status = dbwrap_parse_record(db, key, idmap_autorid_config_parser,
     821             :                                      &state);
     822           0 :         if (!NT_STATUS_IS_OK(status)) {
     823           0 :                 DEBUG(1, ("Error while retrieving config: %s\n",
     824             :                           nt_errstr(status)));
     825           0 :                 return status;
     826             :         }
     827             : 
     828           0 :         if (state.configstr == NULL) {
     829           0 :                 DEBUG(1, ("Error while retrieving config\n"));
     830           0 :                 return NT_STATUS_NO_MEMORY;
     831             :         }
     832             : 
     833           0 :         DEBUG(5, ("found CONFIG: %s\n", state.configstr));
     834             : 
     835           0 :         *result = state.configstr;
     836           0 :         return NT_STATUS_OK;
     837             : }
     838             : 
     839           0 : bool idmap_autorid_parse_configstr(const char *configstr,
     840             :                                    struct autorid_global_config *cfg)
     841             : {
     842             :         unsigned long minvalue, rangesize, maxranges;
     843             : 
     844           0 :         if (sscanf(configstr,
     845             :                    "minvalue:%lu rangesize:%lu maxranges:%lu",
     846             :                    &minvalue, &rangesize, &maxranges) != 3) {
     847           0 :                 DEBUG(1,
     848             :                       ("Found invalid configuration data. "
     849             :                        "Creating new config\n"));
     850           0 :                 return false;
     851             :         }
     852             : 
     853           0 :         cfg->minvalue = minvalue;
     854           0 :         cfg->rangesize = rangesize;
     855           0 :         cfg->maxranges = maxranges;
     856             : 
     857           0 :         return true;
     858             : }
     859             : 
     860           0 : NTSTATUS idmap_autorid_loadconfig(struct db_context *db,
     861             :                                   struct autorid_global_config *result)
     862             : {
     863           0 :         struct autorid_global_config cfg = {0};
     864             :         NTSTATUS status;
     865             :         bool ok;
     866           0 :         char *configstr = NULL;
     867             : 
     868           0 :         if (result == NULL) {
     869           0 :                 return NT_STATUS_INVALID_PARAMETER;
     870             :         }
     871             : 
     872           0 :         status = idmap_autorid_getconfigstr(db, db, &configstr);
     873           0 :         if (!NT_STATUS_IS_OK(status)) {
     874           0 :                 return status;
     875             :         }
     876             : 
     877           0 :         ok = idmap_autorid_parse_configstr(configstr, &cfg);
     878           0 :         TALLOC_FREE(configstr);
     879           0 :         if (!ok) {
     880           0 :                 return NT_STATUS_INVALID_PARAMETER;
     881             :         }
     882             : 
     883           0 :         DEBUG(10, ("Loaded previously stored configuration "
     884             :                    "minvalue:%d rangesize:%d\n",
     885             :                    cfg.minvalue, cfg.rangesize));
     886             : 
     887           0 :         *result = cfg;
     888             : 
     889           0 :         return NT_STATUS_OK;
     890             : }
     891             : 
     892           0 : NTSTATUS idmap_autorid_saveconfig(struct db_context *db,
     893             :                                   struct autorid_global_config *cfg)
     894             : {
     895             : 
     896           0 :         struct autorid_global_config storedconfig = {0};
     897           0 :         NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
     898             :         TDB_DATA data;
     899             :         char *cfgstr;
     900             :         uint32_t hwm;
     901           0 :         TALLOC_CTX *frame = talloc_stackframe();
     902             : 
     903           0 :         DEBUG(10, ("New configuration provided for storing is "
     904             :                    "minvalue:%d rangesize:%d maxranges:%d\n",
     905             :                    cfg->minvalue, cfg->rangesize, cfg->maxranges));
     906             : 
     907           0 :         if (cfg->rangesize < 2000) {
     908           0 :                 DEBUG(1, ("autorid rangesize must be at least 2000\n"));
     909           0 :                 goto done;
     910             :         }
     911             : 
     912           0 :         if (cfg->maxranges == 0) {
     913           0 :                 DEBUG(1, ("An autorid maxranges value of 0 is invalid. "
     914             :                           "Must have at least one range available.\n"));
     915           0 :                 goto done;
     916             :         }
     917             : 
     918           0 :         status = idmap_autorid_loadconfig(db, &storedconfig);
     919           0 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
     920           0 :                 DEBUG(5, ("No configuration found. Storing initial "
     921             :                           "configuration.\n"));
     922           0 :                 storedconfig = *cfg;
     923           0 :         } else if (!NT_STATUS_IS_OK(status)) {
     924           0 :                 DEBUG(1, ("Error loading configuration: %s\n",
     925             :                           nt_errstr(status)));
     926           0 :                 goto done;
     927             :         }
     928             : 
     929             :         /* did the minimum value or rangesize change? */
     930           0 :         if ((storedconfig.minvalue != cfg->minvalue) ||
     931           0 :             (storedconfig.rangesize != cfg->rangesize))
     932             :         {
     933           0 :                 DEBUG(1, ("New configuration values for rangesize or "
     934             :                           "minimum uid value conflict with previously "
     935             :                           "used values! Not storing new config.\n"));
     936           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     937           0 :                 goto done;
     938             :         }
     939             : 
     940           0 :         status = dbwrap_fetch_uint32_bystring(db, HWM, &hwm);
     941           0 :         if (!NT_STATUS_IS_OK(status)) {
     942           0 :                 DEBUG(1, ("Fatal error while fetching current "
     943             :                           "HWM value: %s\n", nt_errstr(status)));
     944           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     945           0 :                 goto done;
     946             :         }
     947             : 
     948             :         /*
     949             :          * has the highest uid value been reduced to setting that is not
     950             :          * sufficient any more for already existing ranges?
     951             :          */
     952           0 :         if (hwm > cfg->maxranges) {
     953           0 :                 DEBUG(1, ("New upper uid limit is too low to cover "
     954             :                           "existing mappings! Not storing new config.\n"));
     955           0 :                 status = NT_STATUS_INVALID_PARAMETER;
     956           0 :                 goto done;
     957             :         }
     958             : 
     959           0 :         cfgstr =
     960           0 :             talloc_asprintf(frame,
     961             :                             "minvalue:%u rangesize:%u maxranges:%u",
     962             :                             cfg->minvalue, cfg->rangesize, cfg->maxranges);
     963             : 
     964           0 :         if (cfgstr == NULL) {
     965           0 :                 status = NT_STATUS_NO_MEMORY;
     966           0 :                 goto done;
     967             :         }
     968             : 
     969           0 :         data = string_tdb_data(cfgstr);
     970             : 
     971           0 :         status = dbwrap_trans_store_bystring(db, CONFIGKEY, data, TDB_REPLACE);
     972             : 
     973           0 : done:
     974           0 :         TALLOC_FREE(frame);
     975           0 :         return status;
     976             : }
     977             : 
     978           0 : NTSTATUS idmap_autorid_saveconfigstr(struct db_context *db,
     979             :                                      const char *configstr)
     980             : {
     981             :         bool ok;
     982             :         NTSTATUS status;
     983             :         struct autorid_global_config cfg;
     984             : 
     985           0 :         ok = idmap_autorid_parse_configstr(configstr, &cfg);
     986           0 :         if (!ok) {
     987           0 :                 return NT_STATUS_INVALID_PARAMETER;
     988             :         }
     989             : 
     990           0 :         status = idmap_autorid_saveconfig(db, &cfg);
     991           0 :         return status;
     992             : }
     993             : 
     994             : 
     995             : /*
     996             :  * iteration: Work on all range mappings for a given domain
     997             :  */
     998             : 
     999             : struct domain_range_visitor_ctx {
    1000             :         const char *domsid;
    1001             :         NTSTATUS (*fn)(struct db_context *db,
    1002             :                        const char *domsid,
    1003             :                        uint32_t index,
    1004             :                        uint32_t rangenum,
    1005             :                        void *private_data);
    1006             :         void *private_data;
    1007             :         int count; /* number of records worked on */
    1008             : };
    1009             : 
    1010           0 : static int idmap_autorid_visit_domain_range(struct db_record *rec,
    1011             :                                             void *private_data)
    1012             : {
    1013             :         struct domain_range_visitor_ctx *vi;
    1014             :         char *domsid;
    1015             :         char *sep;
    1016           0 :         uint32_t range_index = 0;
    1017           0 :         uint32_t rangenum = 0;
    1018             :         TDB_DATA key, value;
    1019             :         NTSTATUS status;
    1020           0 :         int ret = 0;
    1021             :         struct db_context *db;
    1022             : 
    1023           0 :         vi = talloc_get_type_abort(private_data,
    1024             :                                    struct domain_range_visitor_ctx);
    1025             : 
    1026           0 :         key = dbwrap_record_get_key(rec);
    1027             : 
    1028             :         /*
    1029             :          * split string "<sid>[#<index>]" into sid string and index number
    1030             :          */
    1031             : 
    1032           0 :         domsid = (char *)key.dptr;
    1033             : 
    1034           0 :         DEBUG(10, ("idmap_autorid_visit_domain_range: visiting key '%s'\n",
    1035             :                    domsid));
    1036             : 
    1037           0 :         sep = strrchr(domsid, '#');
    1038           0 :         if (sep != NULL) {
    1039             :                 char *index_str;
    1040           0 :                 *sep = '\0';
    1041           0 :                 index_str = sep+1;
    1042           0 :                 if (sscanf(index_str, "%"SCNu32, &range_index) != 1) {
    1043           0 :                         DEBUG(10, ("Found separator '#' but '%s' is not a "
    1044             :                                    "valid range index. Skipping record\n",
    1045             :                                    index_str));
    1046           0 :                         goto done;
    1047             :                 }
    1048             :         }
    1049             : 
    1050           0 :         if (!idmap_autorid_validate_sid(domsid)) {
    1051           0 :                 DEBUG(10, ("String '%s' is not a valid sid. "
    1052             :                            "Skipping record.\n", domsid));
    1053           0 :                 goto done;
    1054             :         }
    1055             : 
    1056           0 :         if ((vi->domsid != NULL) && (strcmp(domsid, vi->domsid) != 0)) {
    1057           0 :                 DEBUG(10, ("key sid '%s' does not match requested sid '%s'.\n",
    1058             :                            domsid, vi->domsid));
    1059           0 :                 goto done;
    1060             :         }
    1061             : 
    1062           0 :         value = dbwrap_record_get_value(rec);
    1063             : 
    1064           0 :         if (value.dsize != sizeof(uint32_t)) {
    1065             :                 /* it might be a mapping of a well known sid */
    1066           0 :                 DEBUG(10, ("value size %u != sizeof(uint32_t) for sid '%s', "
    1067             :                            "skipping.\n", (unsigned)value.dsize, vi->domsid));
    1068           0 :                 goto done;
    1069             :         }
    1070             : 
    1071           0 :         rangenum = IVAL(value.dptr, 0);
    1072             : 
    1073           0 :         db = dbwrap_record_get_db(rec);
    1074             : 
    1075           0 :         status = vi->fn(db, domsid, range_index, rangenum, vi->private_data);
    1076           0 :         if (!NT_STATUS_IS_OK(status)) {
    1077           0 :                 ret = -1;
    1078           0 :                 goto done;
    1079             :         }
    1080             : 
    1081           0 :         vi->count++;
    1082           0 :         ret = 0;
    1083             : 
    1084           0 : done:
    1085           0 :         return ret;
    1086             : }
    1087             : 
    1088           0 : static NTSTATUS idmap_autorid_iterate_domain_ranges_int(struct db_context *db,
    1089             :                                 const char *domsid,
    1090             :                                 NTSTATUS (*fn)(struct db_context *db,
    1091             :                                                const char *domsid,
    1092             :                                                uint32_t index,
    1093             :                                                uint32_t rangnum,
    1094             :                                                void *private_data),
    1095             :                                 void *private_data,
    1096             :                                 int *count,
    1097             :                                 NTSTATUS (*traverse)(struct db_context *db,
    1098             :                                           int (*f)(struct db_record *, void *),
    1099             :                                           void *private_data,
    1100             :                                           int *count))
    1101             : {
    1102             :         NTSTATUS status;
    1103             :         struct domain_range_visitor_ctx *vi;
    1104           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1105             : 
    1106           0 :         if (domsid == NULL) {
    1107           0 :                 DEBUG(10, ("No sid provided, operating on all ranges\n"));
    1108             :         }
    1109             : 
    1110           0 :         if (fn == NULL) {
    1111           0 :                 DEBUG(1, ("Error: missing visitor callback\n"));
    1112           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1113           0 :                 goto done;
    1114             :         }
    1115             : 
    1116           0 :         vi = talloc_zero(frame, struct domain_range_visitor_ctx);
    1117           0 :         if (vi == NULL) {
    1118           0 :                 status = NT_STATUS_NO_MEMORY;
    1119           0 :                 goto done;
    1120             :         }
    1121             : 
    1122           0 :         vi->domsid = domsid;
    1123           0 :         vi->fn = fn;
    1124           0 :         vi->private_data = private_data;
    1125             : 
    1126           0 :         status = traverse(db, idmap_autorid_visit_domain_range, vi, NULL);
    1127           0 :         if (!NT_STATUS_IS_OK(status)) {
    1128           0 :                 goto done;
    1129             :         }
    1130             : 
    1131           0 :         if (count != NULL) {
    1132           0 :                 *count = vi->count;
    1133             :         }
    1134             : 
    1135           0 : done:
    1136           0 :         talloc_free(frame);
    1137           0 :         return status;
    1138             : }
    1139             : 
    1140           0 : NTSTATUS idmap_autorid_iterate_domain_ranges(struct db_context *db,
    1141             :                                         const char *domsid,
    1142             :                                         NTSTATUS (*fn)(struct db_context *db,
    1143             :                                                        const char *domsid,
    1144             :                                                        uint32_t index,
    1145             :                                                        uint32_t rangenum,
    1146             :                                                        void *private_data),
    1147             :                                         void *private_data,
    1148             :                                         int *count)
    1149             : {
    1150             :         NTSTATUS status;
    1151             : 
    1152           0 :         status = idmap_autorid_iterate_domain_ranges_int(db,
    1153             :                                                          domsid,
    1154             :                                                          fn,
    1155             :                                                          private_data,
    1156             :                                                          count,
    1157             :                                                          dbwrap_traverse);
    1158             : 
    1159           0 :         return status;
    1160             : }
    1161             : 
    1162             : 
    1163           0 : NTSTATUS idmap_autorid_iterate_domain_ranges_read(struct db_context *db,
    1164             :                                         const char *domsid,
    1165             :                                         NTSTATUS (*fn)(struct db_context *db,
    1166             :                                                        const char *domsid,
    1167             :                                                        uint32_t index,
    1168             :                                                        uint32_t rangenum,
    1169             :                                                        void *count),
    1170             :                                         void *private_data,
    1171             :                                         int *count)
    1172             : {
    1173             :         NTSTATUS status;
    1174             : 
    1175           0 :         status = idmap_autorid_iterate_domain_ranges_int(db,
    1176             :                                                          domsid,
    1177             :                                                          fn,
    1178             :                                                          private_data,
    1179             :                                                          count,
    1180             :                                                          dbwrap_traverse_read);
    1181             : 
    1182           0 :         return status;
    1183             : }
    1184             : 
    1185             : 
    1186             : /*
    1187             :  * Delete all ranges configured for a given domain
    1188             :  */
    1189             : 
    1190             : struct delete_domain_ranges_visitor_ctx {
    1191             :         bool force;
    1192             : };
    1193             : 
    1194           0 : static NTSTATUS idmap_autorid_delete_domain_ranges_visitor(
    1195             :                                                 struct db_context *db,
    1196             :                                                 const char *domsid,
    1197             :                                                 uint32_t domain_range_index,
    1198             :                                                 uint32_t rangenum,
    1199             :                                                 void *private_data)
    1200             : {
    1201             :         struct delete_domain_ranges_visitor_ctx *ctx;
    1202             :         NTSTATUS status;
    1203             : 
    1204           0 :         ctx = (struct delete_domain_ranges_visitor_ctx *)private_data;
    1205             : 
    1206           0 :         status = idmap_autorid_delete_range_by_sid(
    1207           0 :                                 db, domsid, domain_range_index, ctx->force);
    1208           0 :         return status;
    1209             : }
    1210             : 
    1211             : struct idmap_autorid_delete_domain_ranges_ctx {
    1212             :         const char *domsid;
    1213             :         bool force;
    1214             :         int count; /* output: count records operated on */
    1215             : };
    1216             : 
    1217           0 : static NTSTATUS idmap_autorid_delete_domain_ranges_action(struct db_context *db,
    1218             :                                                           void *private_data)
    1219             : {
    1220             :         struct idmap_autorid_delete_domain_ranges_ctx *ctx;
    1221             :         struct delete_domain_ranges_visitor_ctx visitor_ctx;
    1222             :         int count;
    1223             :         NTSTATUS status;
    1224             : 
    1225           0 :         ctx = (struct idmap_autorid_delete_domain_ranges_ctx *)private_data;
    1226             : 
    1227           0 :         ZERO_STRUCT(visitor_ctx);
    1228           0 :         visitor_ctx.force = ctx->force;
    1229             : 
    1230           0 :         status = idmap_autorid_iterate_domain_ranges(db,
    1231             :                                 ctx->domsid,
    1232             :                                 idmap_autorid_delete_domain_ranges_visitor,
    1233             :                                 &visitor_ctx,
    1234             :                                 &count);
    1235           0 :         if (!NT_STATUS_IS_OK(status)) {
    1236           0 :                 return status;
    1237             :         }
    1238             : 
    1239           0 :         ctx->count = count;
    1240             : 
    1241           0 :         return NT_STATUS_OK;
    1242             : }
    1243             : 
    1244           0 : NTSTATUS idmap_autorid_delete_domain_ranges(struct db_context *db,
    1245             :                                             const char *domsid,
    1246             :                                             bool force,
    1247             :                                             int *count)
    1248             : {
    1249             :         NTSTATUS status;
    1250             :         struct idmap_autorid_delete_domain_ranges_ctx ctx;
    1251             : 
    1252           0 :         ZERO_STRUCT(ctx);
    1253           0 :         ctx.domsid = domsid;
    1254           0 :         ctx.force = force;
    1255             : 
    1256           0 :         status = dbwrap_trans_do(db, idmap_autorid_delete_domain_ranges_action,
    1257             :                                  &ctx);
    1258           0 :         if (!NT_STATUS_IS_OK(status)) {
    1259           0 :                 return status;
    1260             :         }
    1261             : 
    1262           0 :         *count = ctx.count;
    1263             : 
    1264           0 :         return NT_STATUS_OK;
    1265             : }

Generated by: LCOV version 1.13