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

Generated by: LCOV version 1.14