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

Generated by: LCOV version 1.14