Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/winbindd/idmap_tdb.c

    r414 r745  
    88   Copyright (C) Jeremy Allison 2006
    99   Copyright (C) Simo Sorce 2003-2006
    10    
     10   Copyright (C) Michael Adam 2009-2010
     11
    1112   This program is free software; you can redistribute it and/or modify
    1213   it under the terms of the GNU General Public License as published by
    1314   the Free Software Foundation; either version 3 of the License, or
    1415   (at your option) any later version.
    15    
     16
    1617   This program is distributed in the hope that it will be useful,
    1718   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1819   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1920   GNU General Public License for more details.
    20    
     21
    2122   You should have received a copy of the GNU General Public License
    2223   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2425
    2526#include "includes.h"
     27#include "system/filesys.h"
    2628#include "winbindd.h"
     29#include "idmap.h"
     30#include "idmap_rw.h"
     31#include "dbwrap.h"
     32#include "../libcli/security/security.h"
     33#include "util_tdb.h"
    2734
    2835#undef DBGC_CLASS
     
    3340
    3441#define IDMAP_VERSION 2
     42
     43struct idmap_tdb_context {
     44        struct db_context *db;
     45        struct idmap_rw_ops *rw_ops;
     46};
    3547
    3648/* High water mark keys */
    3749#define HWM_GROUP  "GROUP HWM"
    3850#define HWM_USER   "USER HWM"
    39 
    40 static struct idmap_tdb_state {
    41 
    42         /* User and group id pool */
    43         uid_t low_uid, high_uid;               /* Range of uids to allocate */
    44         gid_t low_gid, high_gid;               /* Range of gids to allocate */
    45 
    46 } idmap_tdb_state;
    4751
    4852struct convert_fn_state {
     
    6165        char *p;
    6266        NTSTATUS status;
    63         DOM_SID sid;
     67        struct dom_sid sid;
    6468        uint32 rid;
    6569        fstring keystr;
     
    98102        rid = atoi(p);
    99103
    100         sid_copy(&sid, &domain->sid);
    101         sid_append_rid(&sid, rid);
     104        sid_compose(&sid, &domain->sid, rid);
    102105
    103106        sid_to_fstring(keystr, &sid);
     
    138141*****************************************************************************/
    139142
    140 static bool idmap_tdb_upgrade(struct db_context *db)
     143static bool idmap_tdb_upgrade(struct idmap_domain *dom, struct db_context *db)
    141144{
    142145        int32 vers;
     
    164167                        wm = IREV(wm);
    165168                }  else {
    166                         wm = idmap_tdb_state.low_uid;
     169                        wm = dom->low_id;
    167170                }
    168171
     
    176179                        wm = IREV(wm);
    177180                } else {
    178                         wm = idmap_tdb_state.low_gid;
     181                        wm = dom->low_id;
    179182                }
    180183
     
    197200
    198201        if (dbwrap_store_int32(db, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
    199                 DEBUG(0, ("Unable to store idmap version in databse\n"));
     202                DEBUG(0, ("Unable to store idmap version in database\n"));
    200203                return False;
    201204        }
     
    204207}
    205208
    206 static NTSTATUS idmap_tdb_load_ranges(void)
    207 {
    208         uid_t low_uid = 0;
    209         uid_t high_uid = 0;
    210         gid_t low_gid = 0;
    211         gid_t high_gid = 0;
    212 
    213         if (!lp_idmap_uid(&low_uid, &high_uid)) {
    214                 DEBUG(1, ("idmap uid missing\n"));
    215                 return NT_STATUS_UNSUCCESSFUL;
    216         }
    217 
    218         if (!lp_idmap_gid(&low_gid, &high_gid)) {
    219                 DEBUG(1, ("idmap gid missing\n"));
    220                 return NT_STATUS_UNSUCCESSFUL;
    221         }
    222 
    223         idmap_tdb_state.low_uid = low_uid;
    224         idmap_tdb_state.high_uid = high_uid;
    225         idmap_tdb_state.low_gid = low_gid;
    226         idmap_tdb_state.high_gid = high_gid;
    227 
    228         if (idmap_tdb_state.high_uid <= idmap_tdb_state.low_uid) {
    229                 DEBUG(1, ("idmap uid range missing or invalid\n"));
    230                 return NT_STATUS_UNSUCCESSFUL;
    231         }
    232 
    233         if (idmap_tdb_state.high_gid <= idmap_tdb_state.low_gid) {
    234                 DEBUG(1, ("idmap gid range missing or invalid\n"));
    235                 return NT_STATUS_UNSUCCESSFUL;
     209static NTSTATUS idmap_tdb_init_hwm(struct idmap_domain *dom)
     210{
     211        int ret;
     212        uint32_t low_uid;
     213        uint32_t low_gid;
     214        bool update_uid = false;
     215        bool update_gid = false;
     216        struct idmap_tdb_context *ctx;
     217
     218        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
     219
     220        low_uid = dbwrap_fetch_int32(ctx->db, HWM_USER);
     221        if (low_uid == -1 || low_uid < dom->low_id) {
     222                update_uid = true;
     223        }
     224
     225        low_gid = dbwrap_fetch_int32(ctx->db, HWM_GROUP);
     226        if (low_gid == -1 || low_gid < dom->low_id) {
     227                update_gid = true;
     228        }
     229
     230        if (!update_uid && !update_gid) {
     231                return NT_STATUS_OK;
     232        }
     233
     234        if (ctx->db->transaction_start(ctx->db) != 0) {
     235                DEBUG(0, ("Unable to start upgrade transaction!\n"));
     236                return NT_STATUS_INTERNAL_DB_ERROR;
     237        }
     238
     239        if (update_uid) {
     240                ret = dbwrap_store_int32(ctx->db, HWM_USER, dom->low_id);
     241                if (ret == -1) {
     242                        ctx->db->transaction_cancel(ctx->db);
     243                        DEBUG(0, ("Unable to initialise user hwm in idmap "
     244                                  "database\n"));
     245                        return NT_STATUS_INTERNAL_DB_ERROR;
     246                }
     247        }
     248
     249        if (update_gid) {
     250                ret = dbwrap_store_int32(ctx->db, HWM_GROUP, dom->low_id);
     251                if (ret == -1) {
     252                        ctx->db->transaction_cancel(ctx->db);
     253                        DEBUG(0, ("Unable to initialise group hwm in idmap "
     254                                  "database\n"));
     255                        return NT_STATUS_INTERNAL_DB_ERROR;
     256                }
     257        }
     258
     259        if (ctx->db->transaction_commit(ctx->db) != 0) {
     260                DEBUG(0, ("Unable to commit upgrade transaction!\n"));
     261                return NT_STATUS_INTERNAL_DB_ERROR;
    236262        }
    237263
     
    239265}
    240266
    241 static NTSTATUS idmap_tdb_open_db(TALLOC_CTX *memctx,
    242                                   bool check_config,
    243                                   struct db_context **dbctx)
    244 {
    245         NTSTATUS ret;
    246         TALLOC_CTX *ctx;
     267static NTSTATUS idmap_tdb_open_db(struct idmap_domain *dom)
     268{
     269        NTSTATUS ret;
     270        TALLOC_CTX *mem_ctx;
    247271        char *tdbfile = NULL;
    248272        struct db_context *db = NULL;
    249273        int32_t version;
    250274        bool config_error = false;
    251 
    252         ret = idmap_tdb_load_ranges();
    253         if (!NT_STATUS_IS_OK(ret)) {
    254                 config_error = true;
    255                 if (check_config) {
    256                         return ret;
    257                 }
     275        struct idmap_tdb_context *ctx;
     276
     277        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
     278
     279        if (ctx->db) {
     280                /* it is already open */
     281                return NT_STATUS_OK;
    258282        }
    259283
    260284        /* use our own context here */
    261         ctx = talloc_stackframe();
     285        mem_ctx = talloc_stackframe();
    262286
    263287        /* use the old database if present */
     
    272296
    273297        /* Open idmap repository */
    274         db = db_open(ctx, tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
     298        db = db_open(mem_ctx, tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
    275299        if (!db) {
    276300                DEBUG(0, ("Unable to open idmap database\n"));
     
    295319                }
    296320
    297                 if (!idmap_tdb_upgrade(db)) {
     321                if (!idmap_tdb_upgrade(dom, db)) {
    298322                        db->transaction_cancel(db);
    299323                        DEBUG(0, ("Unable to open idmap database, it's in an old format, and upgrade failed!\n"));
     
    309333        }
    310334
    311         *dbctx = talloc_move(memctx, &db);
    312         ret = NT_STATUS_OK;
     335        ctx->db = talloc_move(ctx, &db);
     336
     337        ret = idmap_tdb_init_hwm(dom);
    313338
    314339done:
    315         talloc_free(ctx);
     340        talloc_free(mem_ctx);
    316341        return ret;
    317342}
     
    320345 IDMAP ALLOC TDB BACKEND
    321346**********************************************************************/
    322  
    323 static struct db_context *idmap_alloc_db;
    324 
    325 /**********************************
    326  Initialise idmap alloc database.
    327 **********************************/
    328 
    329 static NTSTATUS idmap_tdb_alloc_init( const char *params )
    330 {
    331         int ret;
    332         NTSTATUS status;
    333         uint32_t low_uid;
    334         uint32_t low_gid;
    335         bool update_uid = false;
    336         bool update_gid = false;
    337 
    338         status = idmap_tdb_open_db(NULL, true, &idmap_alloc_db);
    339         if (!NT_STATUS_IS_OK(status)) {
    340                 DEBUG(0, ("idmap will be unable to map foreign SIDs: %s\n",
    341                           nt_errstr(status)));
    342                 return status;
    343         }
    344 
    345         low_uid = dbwrap_fetch_int32(idmap_alloc_db, HWM_USER);
    346         if (low_uid == -1 || low_uid < idmap_tdb_state.low_uid) {
    347                 update_uid = true;
    348         }
    349 
    350         low_gid = dbwrap_fetch_int32(idmap_alloc_db, HWM_GROUP);
    351         if (low_gid == -1 || low_gid < idmap_tdb_state.low_gid) {
    352                 update_gid = true;
    353         }
    354 
    355         if (!update_uid && !update_gid) {
    356                 return NT_STATUS_OK;
    357         }
    358 
    359         if (idmap_alloc_db->transaction_start(idmap_alloc_db) != 0) {
    360                 TALLOC_FREE(idmap_alloc_db);
    361                 DEBUG(0, ("Unable to start upgrade transaction!\n"));
    362                 return NT_STATUS_INTERNAL_DB_ERROR;
    363         }
    364 
    365         if (update_uid) {
    366                 ret = dbwrap_store_int32(idmap_alloc_db, HWM_USER,
    367                                          idmap_tdb_state.low_uid);
    368                 if (ret == -1) {
    369                         idmap_alloc_db->transaction_cancel(idmap_alloc_db);
    370                         TALLOC_FREE(idmap_alloc_db);
    371                         DEBUG(0, ("Unable to initialise user hwm in idmap "
    372                                   "database\n"));
    373                         return NT_STATUS_INTERNAL_DB_ERROR;
    374                 }
    375         }
    376 
    377         if (update_gid) {
    378                 ret = dbwrap_store_int32(idmap_alloc_db, HWM_GROUP,
    379                                          idmap_tdb_state.low_gid);
    380                 if (ret == -1) {
    381                         idmap_alloc_db->transaction_cancel(idmap_alloc_db);
    382                         TALLOC_FREE(idmap_alloc_db);
    383                         DEBUG(0, ("Unable to initialise group hwm in idmap "
    384                                   "database\n"));
    385                         return NT_STATUS_INTERNAL_DB_ERROR;
    386                 }
    387         }
    388 
    389         if (idmap_alloc_db->transaction_commit(idmap_alloc_db) != 0) {
    390                 TALLOC_FREE(idmap_alloc_db);
    391                 DEBUG(0, ("Unable to commit upgrade transaction!\n"));
    392                 return NT_STATUS_INTERNAL_DB_ERROR;
    393         }
    394 
    395         return NT_STATUS_OK;
    396 }
    397347
    398348/**********************************
     
    400350**********************************/
    401351
    402 static NTSTATUS idmap_tdb_allocate_id(struct unixid *xid)
    403 {
    404         NTSTATUS ret;
     352struct idmap_tdb_allocate_id_context {
    405353        const char *hwmkey;
    406354        const char *hwmtype;
    407355        uint32_t high_hwm;
    408356        uint32_t hwm;
    409         int res;
     357};
     358
     359static NTSTATUS idmap_tdb_allocate_id_action(struct db_context *db,
     360                                             void *private_data)
     361{
     362        NTSTATUS ret;
     363        struct idmap_tdb_allocate_id_context *state;
     364        uint32_t hwm;
     365
     366        state = (struct idmap_tdb_allocate_id_context *)private_data;
     367
     368        hwm = dbwrap_fetch_int32(db, state->hwmkey);
     369        if (hwm == -1) {
     370                ret = NT_STATUS_INTERNAL_DB_ERROR;
     371                goto done;
     372        }
     373
     374        /* check it is in the range */
     375        if (hwm > state->high_hwm) {
     376                DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
     377                          state->hwmtype, (unsigned long)state->high_hwm));
     378                ret = NT_STATUS_UNSUCCESSFUL;
     379                goto done;
     380        }
     381
     382        /* fetch a new id and increment it */
     383        ret = dbwrap_trans_change_uint32_atomic(db, state->hwmkey, &hwm, 1);
     384        if (!NT_STATUS_IS_OK(ret)) {
     385                DEBUG(0, ("Fatal error while fetching a new %s value: %s\n!",
     386                          state->hwmtype, nt_errstr(ret)));
     387                goto done;
     388        }
     389
     390        /* recheck it is in the range */
     391        if (hwm > state->high_hwm) {
     392                DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
     393                          state->hwmtype, (unsigned long)state->high_hwm));
     394                ret = NT_STATUS_UNSUCCESSFUL;
     395                goto done;
     396        }
     397
     398        ret = NT_STATUS_OK;
     399        state->hwm = hwm;
     400
     401done:
     402        return ret;
     403}
     404
     405static NTSTATUS idmap_tdb_allocate_id(struct idmap_domain *dom,
     406                                      struct unixid *xid)
     407{
     408        const char *hwmkey;
     409        const char *hwmtype;
     410        uint32_t high_hwm;
     411        uint32_t hwm = 0;
     412        NTSTATUS status;
     413        struct idmap_tdb_allocate_id_context state;
     414        struct idmap_tdb_context *ctx;
     415
     416        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    410417
    411418        /* Get current high water mark */
     
    415422                hwmkey = HWM_USER;
    416423                hwmtype = "UID";
    417                 high_hwm = idmap_tdb_state.high_uid;
    418424                break;
    419425
     
    421427                hwmkey = HWM_GROUP;
    422428                hwmtype = "GID";
    423                 high_hwm = idmap_tdb_state.high_gid;
    424429                break;
    425430
     
    429434        }
    430435
    431         res = idmap_alloc_db->transaction_start(idmap_alloc_db);
    432         if (res != 0) {
    433                 DEBUG(1, (__location__ " Failed to start transaction.\n"));
    434                 return NT_STATUS_UNSUCCESSFUL;
    435         }
    436 
    437         if ((hwm = dbwrap_fetch_int32(idmap_alloc_db, hwmkey)) == -1) {
    438                 idmap_alloc_db->transaction_cancel(idmap_alloc_db);
    439                 return NT_STATUS_INTERNAL_DB_ERROR;
    440         }
    441 
    442         /* check it is in the range */
    443         if (hwm > high_hwm) {
    444                 DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
    445                           hwmtype, (unsigned long)high_hwm));
    446                 idmap_alloc_db->transaction_cancel(idmap_alloc_db);
    447                 return NT_STATUS_UNSUCCESSFUL;
    448         }
    449 
    450         /* fetch a new id and increment it */
    451         ret = dbwrap_change_uint32_atomic(idmap_alloc_db, hwmkey, &hwm, 1);
    452         if (!NT_STATUS_IS_OK(ret)) {
    453                 DEBUG(0, ("Fatal error while fetching a new %s value: %s\n!",
    454                           hwmtype, nt_errstr(ret)));
    455                 idmap_alloc_db->transaction_cancel(idmap_alloc_db);
    456                 return ret;
    457         }
    458 
    459         /* recheck it is in the range */
    460         if (hwm > high_hwm) {
    461                 DEBUG(1, ("Fatal Error: %s range full!! (max: %lu)\n",
    462                           hwmtype, (unsigned long)high_hwm));
    463                 idmap_alloc_db->transaction_cancel(idmap_alloc_db);
    464                 return NT_STATUS_UNSUCCESSFUL;
    465         }
    466 
    467         res = idmap_alloc_db->transaction_commit(idmap_alloc_db);
    468         if (res != 0) {
    469                 DEBUG(1, (__location__ " Failed to commit transaction.\n"));
    470                 return NT_STATUS_UNSUCCESSFUL;
    471         }
    472 
    473         xid->id = hwm;
    474         DEBUG(10,("New %s = %d\n", hwmtype, hwm));
    475 
    476         return NT_STATUS_OK;
    477 }
    478 
    479 /**********************************
    480  Get current highest id.
    481 **********************************/
    482 
    483 static NTSTATUS idmap_tdb_get_hwm(struct unixid *xid)
    484 {
    485         const char *hwmkey;
    486         const char *hwmtype;
    487         uint32_t hwm;
    488         uint32_t high_hwm;
    489 
    490         /* Get current high water mark */
    491         switch (xid->type) {
    492 
    493         case ID_TYPE_UID:
    494                 hwmkey = HWM_USER;
    495                 hwmtype = "UID";
    496                 high_hwm = idmap_tdb_state.high_uid;
    497                 break;
    498 
    499         case ID_TYPE_GID:
    500                 hwmkey = HWM_GROUP;
    501                 hwmtype = "GID";
    502                 high_hwm = idmap_tdb_state.high_gid;
    503                 break;
    504 
    505         default:
    506                 return NT_STATUS_INVALID_PARAMETER;
    507         }
    508 
    509         if ((hwm = dbwrap_fetch_int32(idmap_alloc_db, hwmkey)) == -1) {
    510                 return NT_STATUS_INTERNAL_DB_ERROR;
    511         }
    512 
    513         xid->id = hwm;
    514 
    515         /* Warn if it is out of range */
    516         if (hwm >= high_hwm) {
    517                 DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
    518                           hwmtype, (unsigned long)high_hwm));
    519         }
    520 
    521         return NT_STATUS_OK;
    522 }
    523 
    524 /**********************************
    525  Set high id.
    526 **********************************/
    527 
    528 static NTSTATUS idmap_tdb_set_hwm(struct unixid *xid)
    529 {
    530         const char *hwmkey;
    531         const char *hwmtype;
    532         uint32_t hwm;
    533         uint32_t high_hwm;
    534         NTSTATUS ret;
    535 
    536         /* Get current high water mark */
    537         switch (xid->type) {
    538 
    539         case ID_TYPE_UID:
    540                 hwmkey = HWM_USER;
    541                 hwmtype = "UID";
    542                 high_hwm = idmap_tdb_state.high_uid;
    543                 break;
    544 
    545         case ID_TYPE_GID:
    546                 hwmkey = HWM_GROUP;
    547                 hwmtype = "GID";
    548                 high_hwm = idmap_tdb_state.high_gid;
    549                 break;
    550 
    551         default:
    552                 return NT_STATUS_INVALID_PARAMETER;
    553         }
    554 
    555         hwm = xid->id;
    556 
    557         /* Warn if it is out of range */
    558         if (hwm >= high_hwm) {
    559                 DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
    560                           hwmtype, (unsigned long)high_hwm));
    561         }
    562 
    563         ret = dbwrap_trans_store_uint32(idmap_alloc_db, hwmkey, hwm);
    564 
    565         return ret;
    566 }
    567 
    568 /**********************************
    569  Close the alloc tdb
    570 **********************************/
    571 
    572 static NTSTATUS idmap_tdb_alloc_close(void)
    573 {
    574         TALLOC_FREE(idmap_alloc_db);
    575         return NT_STATUS_OK;
     436        high_hwm = dom->high_id;
     437
     438        state.hwm = hwm;
     439        state.high_hwm = high_hwm;
     440        state.hwmtype = hwmtype;
     441        state.hwmkey = hwmkey;
     442
     443        status = dbwrap_trans_do(ctx->db, idmap_tdb_allocate_id_action,
     444                                 &state);
     445
     446        if (NT_STATUS_IS_OK(status)) {
     447                xid->id = state.hwm;
     448                DEBUG(10,("New %s = %d\n", hwmtype, state.hwm));
     449        } else {
     450                DEBUG(1, ("Error allocating a new %s\n", hwmtype));
     451        }
     452
     453        return status;
     454}
     455
     456/**
     457 * Allocate a new unix-ID.
     458 * For now this is for the default idmap domain only.
     459 * Should be extended later on.
     460 */
     461static NTSTATUS idmap_tdb_get_new_id(struct idmap_domain *dom,
     462                                     struct unixid *id)
     463{
     464        NTSTATUS ret;
     465
     466        if (!strequal(dom->name, "*")) {
     467                DEBUG(3, ("idmap_tdb_get_new_id: "
     468                          "Refusing allocation of a new unixid for domain'%s'. "
     469                          "Currently only supported for the default "
     470                          "domain \"*\".\n",
     471                           dom->name));
     472                return NT_STATUS_NOT_IMPLEMENTED;
     473        }
     474
     475        ret = idmap_tdb_allocate_id(dom, id);
     476
     477        return ret;
    576478}
    577479
     
    579481 IDMAP MAPPING TDB BACKEND
    580482**********************************************************************/
    581  
    582 struct idmap_tdb_context {
    583         struct db_context *db;
    584         uint32_t filter_low_id;
    585         uint32_t filter_high_id;
    586 };
    587483
    588484/*****************************
     
    590486*****************************/
    591487
    592 static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom, const char *params)
     488static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom,
     489                                      const struct id_map *map);
     490
     491static NTSTATUS idmap_tdb_db_init(struct idmap_domain *dom)
    593492{
    594493        NTSTATUS ret;
     
    597496        DEBUG(10, ("idmap_tdb_db_init called for domain '%s'\n", dom->name));
    598497
    599         ctx = talloc(dom, struct idmap_tdb_context);
     498        ctx = talloc_zero(dom, struct idmap_tdb_context);
    600499        if ( ! ctx) {
    601500                DEBUG(0, ("Out of memory!\n"));
     
    603502        }
    604503
     504        /* load backend specific configuration here: */
     505#if 0
    605506        if (strequal(dom->name, "*")) {
    606                 uid_t low_uid = 0;
    607                 uid_t high_uid = 0;
    608                 gid_t low_gid = 0;
    609                 gid_t high_gid = 0;
    610 
    611                 ctx->filter_low_id = 0;
    612                 ctx->filter_high_id = 0;
    613 
    614                 if (lp_idmap_uid(&low_uid, &high_uid)) {
    615                         ctx->filter_low_id = low_uid;
    616                         ctx->filter_high_id = high_uid;
    617                 } else {
    618                         DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
    619                 }
    620 
    621                 if (lp_idmap_gid(&low_gid, &high_gid)) {
    622                         if ((low_gid != low_uid) || (high_gid != high_uid)) {
    623                                 DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
    624                                       " ranges do not agree -- building "
    625                                       "intersection\n"));
    626                                 ctx->filter_low_id = MAX(ctx->filter_low_id,
    627                                                          low_gid);
    628                                 ctx->filter_high_id = MIN(ctx->filter_high_id,
    629                                                           high_gid);
    630                         }
    631                 } else {
    632                         DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
    633                 }
    634507        } else {
    635                 char *config_option = NULL;
    636                 const char *range;
    637 
    638                 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
    639                 if ( ! config_option) {
    640                         DEBUG(0, ("Out of memory!\n"));
    641                         ret = NT_STATUS_NO_MEMORY;
    642                         goto failed;
    643                 }
    644 
    645                 range = lp_parm_const_string(-1, config_option, "range", NULL);
    646                 if (( ! range) ||
    647                     (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2))
    648                 {
    649                         ctx->filter_low_id = 0;
    650                         ctx->filter_high_id = 0;
    651                 }
    652 
    653                 talloc_free(config_option);
    654         }
    655 
    656         if (ctx->filter_low_id > ctx->filter_high_id) {
    657                 ctx->filter_low_id = 0;
    658                 ctx->filter_high_id = 0;
    659         }
    660 
    661         DEBUG(10, ("idmap_tdb_db_init: filter range %u-%u loaded for domain "
    662               "'%s'\n", ctx->filter_low_id, ctx->filter_high_id, dom->name));
    663 
    664         ret = idmap_tdb_open_db(ctx, false, &ctx->db);
     508        }
     509#endif
     510
     511        ctx->rw_ops = talloc_zero(ctx, struct idmap_rw_ops);
     512        if (ctx->rw_ops == NULL) {
     513                DEBUG(0, ("Out of memory!\n"));
     514                ret = NT_STATUS_NO_MEMORY;
     515                goto failed;
     516        }
     517
     518        ctx->rw_ops->get_new_id = idmap_tdb_get_new_id;
     519        ctx->rw_ops->set_mapping = idmap_tdb_set_mapping;
     520
     521        dom->private_data = ctx;
     522
     523        ret = idmap_tdb_open_db(dom);
    665524        if ( ! NT_STATUS_IS_OK(ret)) {
    666525                goto failed;
    667526        }
    668527
    669         dom->private_data = ctx;
    670 
    671528        return NT_STATUS_OK;
    672529
     
    675532        return ret;
    676533}
     534
     535
     536/**
     537 * store a mapping in the database
     538 */
     539
     540struct idmap_tdb_set_mapping_context {
     541        const char *ksidstr;
     542        const char *kidstr;
     543};
     544
     545static NTSTATUS idmap_tdb_set_mapping_action(struct db_context *db,
     546                                             void *private_data)
     547{
     548        NTSTATUS ret;
     549        struct idmap_tdb_set_mapping_context *state;
     550
     551        state = (struct idmap_tdb_set_mapping_context *)private_data;
     552
     553        DEBUG(10, ("Storing %s <-> %s map\n", state->ksidstr, state->kidstr));
     554
     555        ret = dbwrap_store_bystring(db, state->ksidstr,
     556                                    string_term_tdb_data(state->kidstr),
     557                                    TDB_REPLACE);
     558        if (!NT_STATUS_IS_OK(ret)) {
     559                DEBUG(0, ("Error storing SID -> ID (%s -> %s): %s\n",
     560                          state->ksidstr, state->kidstr, nt_errstr(ret)));
     561                goto done;
     562        }
     563
     564        ret = dbwrap_store_bystring(db, state->kidstr,
     565                                    string_term_tdb_data(state->ksidstr),
     566                                    TDB_REPLACE);
     567        if (!NT_STATUS_IS_OK(ret)) {
     568                DEBUG(0, ("Error storing ID -> SID (%s -> %s): %s\n",
     569                          state->kidstr, state->ksidstr, nt_errstr(ret)));
     570                goto done;
     571        }
     572
     573        DEBUG(10,("Stored %s <-> %s\n", state->ksidstr, state->kidstr));
     574        ret = NT_STATUS_OK;
     575
     576done:
     577        return ret;
     578}
     579
     580static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom,
     581                                      const struct id_map *map)
     582{
     583        struct idmap_tdb_context *ctx;
     584        NTSTATUS ret;
     585        char *ksidstr, *kidstr;
     586        struct idmap_tdb_set_mapping_context state;
     587
     588        if (!map || !map->sid) {
     589                return NT_STATUS_INVALID_PARAMETER;
     590        }
     591
     592        ksidstr = kidstr = NULL;
     593
     594        /* TODO: should we filter a set_mapping using low/high filters ? */
     595
     596        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
     597
     598        switch (map->xid.type) {
     599
     600        case ID_TYPE_UID:
     601                kidstr = talloc_asprintf(ctx, "UID %lu",
     602                                         (unsigned long)map->xid.id);
     603                break;
     604
     605        case ID_TYPE_GID:
     606                kidstr = talloc_asprintf(ctx, "GID %lu",
     607                                         (unsigned long)map->xid.id);
     608                break;
     609
     610        default:
     611                DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
     612                return NT_STATUS_INVALID_PARAMETER;
     613        }
     614
     615        if (kidstr == NULL) {
     616                DEBUG(0, ("ERROR: Out of memory!\n"));
     617                ret = NT_STATUS_NO_MEMORY;
     618                goto done;
     619        }
     620
     621        ksidstr = sid_string_talloc(ctx, map->sid);
     622        if (ksidstr == NULL) {
     623                DEBUG(0, ("Out of memory!\n"));
     624                ret = NT_STATUS_NO_MEMORY;
     625                goto done;
     626        }
     627
     628        state.ksidstr = ksidstr;
     629        state.kidstr = kidstr;
     630
     631        ret = dbwrap_trans_do(ctx->db, idmap_tdb_set_mapping_action, &state);
     632
     633done:
     634        talloc_free(ksidstr);
     635        talloc_free(kidstr);
     636        return ret;
     637}
     638
     639/**
     640 * Create a new mapping for an unmapped SID, also allocating a new ID.
     641 * This should be run inside a transaction.
     642 *
     643 * TODO:
     644 * Properly integrate this with multi domain idmap config:
     645 * Currently, the allocator is default-config only.
     646 */
     647static NTSTATUS idmap_tdb_new_mapping(struct idmap_domain *dom, struct id_map *map)
     648{
     649        NTSTATUS ret;
     650        struct idmap_tdb_context *ctx;
     651
     652        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
     653
     654        ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map);
     655
     656        return ret;
     657}
     658
    677659
    678660/**********************************
     
    680662**********************************/
    681663
    682 static NTSTATUS idmap_tdb_id_to_sid(struct idmap_tdb_context *ctx, struct id_map *map)
     664static NTSTATUS idmap_tdb_id_to_sid(struct idmap_domain *dom, struct id_map *map)
    683665{
    684666        NTSTATUS ret;
    685667        TDB_DATA data;
    686668        char *keystr;
    687 
    688         if (!ctx || !map) {
     669        struct idmap_tdb_context *ctx;
     670
     671        if (!dom || !map) {
    689672                return NT_STATUS_INVALID_PARAMETER;
    690673        }
    691674
     675        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
     676
    692677        /* apply filters before checking */
    693         if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
    694             (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
     678        if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
    695679                DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
    696                                 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
     680                                map->xid.id, dom->low_id, dom->high_id));
    697681                return NT_STATUS_NONE_MAPPED;
    698682        }
     
    703687                keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
    704688                break;
    705                
     689
    706690        case ID_TYPE_GID:
    707691                keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
     
    732716                goto done;
    733717        }
    734                
     718
    735719        if (!string_to_sid(map->sid, (const char *)data.dptr)) {
    736720                DEBUG(10,("INVALID SID (%s) in record %s\n",
     
    753737**********************************/
    754738
    755 static NTSTATUS idmap_tdb_sid_to_id(struct idmap_tdb_context *ctx, struct id_map *map)
     739static NTSTATUS idmap_tdb_sid_to_id(struct idmap_domain *dom, struct id_map *map)
    756740{
    757741        NTSTATUS ret;
     
    759743        char *keystr;
    760744        unsigned long rec_id = 0;
     745        struct idmap_tdb_context *ctx;
    761746        TALLOC_CTX *tmp_ctx = talloc_stackframe();
     747
     748        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    762749
    763750        keystr = sid_string_talloc(tmp_ctx, map->sid);
     
    794781                DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr));
    795782                ret = NT_STATUS_INTERNAL_DB_ERROR;
     783                goto done;
    796784        }
    797785
    798786        /* apply filters before returning result */
    799         if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
    800             (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
     787        if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
    801788                DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
    802                                 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
     789                                map->xid.id, dom->low_id, dom->high_id));
    803790                ret = NT_STATUS_NONE_MAPPED;
    804791        }
     
    815802static NTSTATUS idmap_tdb_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
    816803{
    817         struct idmap_tdb_context *ctx;
    818804        NTSTATUS ret;
    819805        int i;
     
    823809                ids[i]->status = ID_UNKNOWN;
    824810        }
    825        
    826         ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    827811
    828812        for (i = 0; ids[i]; i++) {
    829                 ret = idmap_tdb_id_to_sid(ctx, ids[i]);
     813                ret = idmap_tdb_id_to_sid(dom, ids[i]);
    830814                if ( ! NT_STATUS_IS_OK(ret)) {
    831815
     
    837821                                continue;
    838822                        }
    839                        
     823
    840824                        /* some fatal error occurred, return immediately */
    841825                        goto done;
     
    856840**********************************/
    857841
     842struct idmap_tdb_sids_to_unixids_context {
     843        struct idmap_domain *dom;
     844        struct id_map **ids;
     845        bool allocate_unmapped;
     846};
     847
     848static NTSTATUS idmap_tdb_sids_to_unixids_action(struct db_context *db,
     849                                                 void *private_data)
     850{
     851        struct idmap_tdb_sids_to_unixids_context *state;
     852        int i;
     853        NTSTATUS ret = NT_STATUS_OK;
     854
     855        state = (struct idmap_tdb_sids_to_unixids_context *)private_data;
     856
     857        DEBUG(10, ("idmap_tdb_sids_to_unixids_action: "
     858                   " domain: [%s], allocate: %s\n",
     859                   state->dom->name,
     860                   state->allocate_unmapped ? "yes" : "no"));
     861
     862        for (i = 0; state->ids[i]; i++) {
     863                if ((state->ids[i]->status == ID_UNKNOWN) ||
     864                    /* retry if we could not map in previous run: */
     865                    (state->ids[i]->status == ID_UNMAPPED))
     866                {
     867                        NTSTATUS ret2;
     868
     869                        ret2 = idmap_tdb_sid_to_id(state->dom, state->ids[i]);
     870                        if (!NT_STATUS_IS_OK(ret2)) {
     871
     872                                /* if it is just a failed mapping, continue */
     873                                if (NT_STATUS_EQUAL(ret2, NT_STATUS_NONE_MAPPED)) {
     874
     875                                        /* make sure it is marked as unmapped */
     876                                        state->ids[i]->status = ID_UNMAPPED;
     877                                        ret = STATUS_SOME_UNMAPPED;
     878                                } else {
     879                                        /* some fatal error occurred, return immediately */
     880                                        ret = ret2;
     881                                        goto done;
     882                                }
     883                        } else {
     884                                /* all ok, id is mapped */
     885                                state->ids[i]->status = ID_MAPPED;
     886                        }
     887                }
     888
     889                if ((state->ids[i]->status == ID_UNMAPPED) &&
     890                    state->allocate_unmapped)
     891                {
     892                        ret = idmap_tdb_new_mapping(state->dom, state->ids[i]);
     893                        if (!NT_STATUS_IS_OK(ret)) {
     894                                goto done;
     895                        }
     896                }
     897        }
     898
     899done:
     900        return ret;
     901}
     902
    858903static NTSTATUS idmap_tdb_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
    859904{
     
    861906        NTSTATUS ret;
    862907        int i;
     908        struct idmap_tdb_sids_to_unixids_context state;
    863909
    864910        /* initialize the status to avoid suprise */
     
    866912                ids[i]->status = ID_UNKNOWN;
    867913        }
    868        
     914
    869915        ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    870916
    871         for (i = 0; ids[i]; i++) {
    872                 ret = idmap_tdb_sid_to_id(ctx, ids[i]);
    873                 if ( ! NT_STATUS_IS_OK(ret)) {
    874 
    875                         /* if it is just a failed mapping continue */
    876                         if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
    877 
    878                                 /* make sure it is marked as unmapped */
    879                                 ids[i]->status = ID_UNMAPPED;
    880                                 continue;
    881                         }
    882                        
    883                         /* some fatal error occurred, return immediately */
    884                         goto done;
    885                 }
    886 
    887                 /* all ok, id is mapped */
    888                 ids[i]->status = ID_MAPPED;
    889         }
    890 
    891         ret = NT_STATUS_OK;
    892 
    893 done:
    894         return ret;
    895 }
    896 
    897 /**********************************
    898  set a mapping.
    899 **********************************/
    900 
    901 static NTSTATUS idmap_tdb_set_mapping(struct idmap_domain *dom,
    902                                       const struct id_map *map)
    903 {
    904         struct idmap_tdb_context *ctx;
    905         NTSTATUS ret;
    906         TDB_DATA ksid, kid;
    907         char *ksidstr, *kidstr;
    908         fstring tmp;
    909 
    910         if (!map || !map->sid) {
    911                 return NT_STATUS_INVALID_PARAMETER;
    912         }
    913 
    914         ksidstr = kidstr = NULL;
    915 
    916         /* TODO: should we filter a set_mapping using low/high filters ? */
    917 
    918         ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    919 
    920         switch (map->xid.type) {
    921 
    922         case ID_TYPE_UID:
    923                 kidstr = talloc_asprintf(ctx, "UID %lu",
    924                                          (unsigned long)map->xid.id);
    925                 break;
    926 
    927         case ID_TYPE_GID:
    928                 kidstr = talloc_asprintf(ctx, "GID %lu",
    929                                          (unsigned long)map->xid.id);
    930                 break;
    931 
    932         default:
    933                 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
    934                 return NT_STATUS_INVALID_PARAMETER;
    935         }
    936 
    937         if (kidstr == NULL) {
    938                 DEBUG(0, ("ERROR: Out of memory!\n"));
    939                 ret = NT_STATUS_NO_MEMORY;
    940                 goto done;
    941         }
    942 
    943         if ((ksidstr = talloc_asprintf(
    944                      ctx, "%s", sid_to_fstring(tmp, map->sid))) == NULL) {
    945                 DEBUG(0, ("Out of memory!\n"));
    946                 ret = NT_STATUS_NO_MEMORY;
    947                 goto done;
    948         }
    949 
    950         DEBUG(10, ("Storing %s <-> %s map\n", ksidstr, kidstr));
    951         kid = string_term_tdb_data(kidstr);
    952         ksid = string_term_tdb_data(ksidstr);
    953 
    954         if (ctx->db->transaction_start(ctx->db) != 0) {
    955                 DEBUG(0, ("Failed to start transaction for %s\n",
    956                           ksidstr));
    957                 ret = NT_STATUS_INTERNAL_DB_ERROR;
    958                 goto done;
    959         }
    960 
    961         ret = dbwrap_store(ctx->db, ksid, kid, TDB_REPLACE);
    962         if (!NT_STATUS_IS_OK(ret)) {
    963                 ctx->db->transaction_cancel(ctx->db);
    964                 DEBUG(0, ("Error storing SID -> ID (%s -> %s): %s\n",
    965                           ksidstr, kidstr, nt_errstr(ret)));
    966                 goto done;
    967         }
    968         ret = dbwrap_store(ctx->db, kid, ksid, TDB_REPLACE);
    969         if (!NT_STATUS_IS_OK(ret)) {
    970                 ctx->db->transaction_cancel(ctx->db);
    971                 DEBUG(0, ("Error storing ID -> SID (%s -> %s): %s\n",
    972                           kidstr, ksidstr, nt_errstr(ret)));
    973                 goto done;
    974         }
    975 
    976         if (ctx->db->transaction_commit(ctx->db) != 0) {
    977                 DEBUG(0, ("Failed to commit transaction for (%s -> %s)\n",
    978                           ksidstr, kidstr));
    979                 ret = NT_STATUS_INTERNAL_DB_ERROR;
    980                 goto done;
    981         }
    982 
    983         DEBUG(10,("Stored %s <-> %s\n", ksidstr, kidstr));
    984         ret = NT_STATUS_OK;
    985 
    986 done:
    987         talloc_free(ksidstr);
    988         talloc_free(kidstr);
    989         return ret;
    990 }
    991 
    992 /**********************************
    993  remove a mapping.
    994 **********************************/
    995 
    996 static NTSTATUS idmap_tdb_remove_mapping(struct idmap_domain *dom,
    997                                          const struct id_map *map)
    998 {
    999         struct idmap_tdb_context *ctx;
    1000         NTSTATUS ret;
    1001         TDB_DATA ksid, kid, data;
    1002         char *ksidstr, *kidstr;
    1003         fstring tmp;
    1004 
    1005         if (!map || !map->sid) {
    1006                 return NT_STATUS_INVALID_PARAMETER;
    1007         }
    1008 
    1009         ksidstr = kidstr = NULL;
    1010         data.dptr = NULL;
    1011 
    1012         /* TODO: should we filter a remove_mapping using low/high filters ? */
    1013 
    1014         ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    1015 
    1016         switch (map->xid.type) {
    1017 
    1018         case ID_TYPE_UID:
    1019                 kidstr = talloc_asprintf(ctx, "UID %lu",
    1020                                          (unsigned long)map->xid.id);
    1021                 break;
    1022 
    1023         case ID_TYPE_GID:
    1024                 kidstr = talloc_asprintf(ctx, "GID %lu",
    1025                                          (unsigned long)map->xid.id);
    1026                 break;
    1027 
    1028         default:
    1029                 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
    1030                 return NT_STATUS_INVALID_PARAMETER;
    1031         }
    1032 
    1033         if (kidstr == NULL) {
    1034                 DEBUG(0, ("ERROR: Out of memory!\n"));
    1035                 ret = NT_STATUS_NO_MEMORY;
    1036                 goto done;
    1037         }
    1038 
    1039         if ((ksidstr = talloc_asprintf(
    1040                      ctx, "%s", sid_to_fstring(tmp, map->sid))) == NULL) {
    1041                 DEBUG(0, ("Out of memory!\n"));
    1042                 ret = NT_STATUS_NO_MEMORY;
    1043                 goto done;
    1044         }
    1045 
    1046         DEBUG(10, ("Checking %s <-> %s map\n", ksidstr, kidstr));
    1047         ksid = string_term_tdb_data(ksidstr);
    1048         kid = string_term_tdb_data(kidstr);
    1049 
    1050         if (ctx->db->transaction_start(ctx->db) != 0) {
    1051                 DEBUG(0, ("Failed to start transaction for %s\n",
    1052                           ksidstr));
    1053                 return NT_STATUS_INTERNAL_DB_ERROR;
    1054         }
    1055 
    1056         /* Check if sid is present in database */
    1057         data = dbwrap_fetch(ctx->db, NULL, ksid);
    1058         if (!data.dptr) {
    1059                 ctx->db->transaction_cancel(ctx->db);
    1060                 DEBUG(10,("Record %s not found\n", ksidstr));
    1061                 ret = NT_STATUS_NONE_MAPPED;
    1062                 goto done;
    1063         }
    1064 
    1065         /* Check if sid is mapped to the specified ID */
    1066         if ((data.dsize != kid.dsize) ||
    1067             (memcmp(data.dptr, kid.dptr, data.dsize) != 0)) {
    1068                 ctx->db->transaction_cancel(ctx->db);
    1069                 DEBUG(10,("Specified SID does not map to specified ID\n"));
    1070                 DEBUGADD(10,("Actual mapping is %s -> %s\n", ksidstr,
    1071                          (const char *)data.dptr));
    1072                 ret = NT_STATUS_NONE_MAPPED;
    1073                 goto done;
    1074         }
    1075 
    1076         DEBUG(10, ("Removing %s <-> %s map\n", ksidstr, kidstr));
    1077 
    1078         /* Delete previous mappings. */
    1079 
    1080         DEBUG(10, ("Deleting existing mapping %s -> %s\n", ksidstr, kidstr ));
    1081         ret = dbwrap_delete(ctx->db, ksid);
    1082         if (!NT_STATUS_IS_OK(ret)) {
    1083                 DEBUG(0,("Warning: Failed to delete %s: %s\n",
    1084                          ksidstr, nt_errstr(ret)));
    1085         }
    1086 
    1087         DEBUG(10,("Deleting existing mapping %s -> %s\n", kidstr, ksidstr ));
    1088         ret = dbwrap_delete(ctx->db, kid);
    1089         if (!NT_STATUS_IS_OK(ret)) {
    1090                 DEBUG(0,("Warning: Failed to delete %s: %s\n",
    1091                          kidstr, nt_errstr(ret)));
    1092         }
    1093 
    1094         if (ctx->db->transaction_commit(ctx->db) != 0) {
    1095                 DEBUG(0, ("Failed to commit transaction for (%s -> %s)\n",
    1096                           ksidstr, kidstr));
    1097                 ret = NT_STATUS_INTERNAL_DB_ERROR;
    1098                 goto done;
    1099         }
    1100 
    1101         ret = NT_STATUS_OK;
    1102 
    1103 done:
    1104         talloc_free(ksidstr);
    1105         talloc_free(kidstr);
    1106         talloc_free(data.dptr);
    1107         return ret;
    1108 }
     917        state.dom = dom;
     918        state.ids = ids;
     919        state.allocate_unmapped = false;
     920
     921        ret = idmap_tdb_sids_to_unixids_action(ctx->db, &state);
     922
     923        if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED) && !dom->read_only) {
     924                state.allocate_unmapped = true;
     925                ret = dbwrap_trans_do(ctx->db,
     926                                      idmap_tdb_sids_to_unixids_action,
     927                                      &state);
     928        }
     929
     930        return ret;
     931}
     932
    1109933
    1110934/**********************************
     
    1112936**********************************/
    1113937
    1114 static NTSTATUS idmap_tdb_close(struct idmap_domain *dom)
    1115 {
    1116         struct idmap_tdb_context *ctx;
    1117 
    1118         if (dom->private_data) {
    1119                 ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    1120 
    1121                 TALLOC_FREE(ctx->db);
    1122         }
    1123         return NT_STATUS_OK;
    1124 }
    1125 
    1126 struct dump_data {
    1127         TALLOC_CTX *memctx;
    1128         struct id_map **maps;
    1129         int *num_maps;
    1130         NTSTATUS ret;
    1131 };
    1132 
    1133 static int idmap_tdb_dump_one_entry(struct db_record *rec, void *pdata)
    1134 {
    1135         struct dump_data *data = talloc_get_type(pdata, struct dump_data);
    1136         struct id_map *maps;
    1137         int num_maps = *data->num_maps;
    1138 
    1139         /* ignore any record but the ones with a SID as key */
    1140         if (strncmp((const char *)rec->key.dptr, "S-", 2) == 0) {
    1141 
    1142                 maps = talloc_realloc(NULL, *data->maps, struct id_map, num_maps+1);
    1143                 if ( ! maps) {
    1144                         DEBUG(0, ("Out of memory!\n"));
    1145                         data->ret = NT_STATUS_NO_MEMORY;
    1146                         return -1;
    1147                 }
    1148                 *data->maps = maps;
    1149                 maps[num_maps].sid = talloc(maps, DOM_SID);
    1150                 if ( ! maps[num_maps].sid) {
    1151                         DEBUG(0, ("Out of memory!\n"));
    1152                         data->ret = NT_STATUS_NO_MEMORY;
    1153                         return -1;
    1154                 }
    1155 
    1156                 if (!string_to_sid(maps[num_maps].sid, (const char *)rec->key.dptr)) {
    1157                         DEBUG(10,("INVALID record %s\n", (const char *)rec->key.dptr));
    1158                         /* continue even with errors */
    1159                         return 0;
    1160                 }
    1161 
    1162                 /* Try a UID record. */
    1163                 if (sscanf((const char *)rec->value.dptr, "UID %u", &(maps[num_maps].xid.id)) == 1) {
    1164                         maps[num_maps].xid.type = ID_TYPE_UID;
    1165                         maps[num_maps].status = ID_MAPPED;
    1166                         *data->num_maps = num_maps + 1;
    1167 
    1168                 /* Try a GID record. */
    1169                 } else
    1170                 if (sscanf((const char *)rec->value.dptr, "GID %u", &(maps[num_maps].xid.id)) == 1) {
    1171                         maps[num_maps].xid.type = ID_TYPE_GID;
    1172                         maps[num_maps].status = ID_MAPPED;
    1173                         *data->num_maps = num_maps + 1;
    1174 
    1175                 /* Unknown record type ! */
    1176                 } else {
    1177                         maps[num_maps].status = ID_UNKNOWN;
    1178                         DEBUG(2, ("Found INVALID record %s -> %s\n",
    1179                                 (const char *)rec->key.dptr,
    1180                                 (const char *)rec->value.dptr));
    1181                         /* do not increment num_maps */
    1182                 }
    1183         }
    1184 
    1185         return 0;
    1186 }
    1187 
    1188 /**********************************
    1189  Dump all mappings out
    1190 **********************************/
    1191 
    1192 static NTSTATUS idmap_tdb_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps)
    1193 {
    1194         struct idmap_tdb_context *ctx;
    1195         struct dump_data *data;
    1196         NTSTATUS ret = NT_STATUS_OK;
    1197 
    1198         ctx = talloc_get_type(dom->private_data, struct idmap_tdb_context);
    1199 
    1200         data = TALLOC_ZERO_P(ctx, struct dump_data);
    1201         if ( ! data) {
    1202                 DEBUG(0, ("Out of memory!\n"));
    1203                 return NT_STATUS_NO_MEMORY;
    1204         }
    1205         data->maps = maps;
    1206         data->num_maps = num_maps;
    1207         data->ret = NT_STATUS_OK;
    1208 
    1209         ctx->db->traverse_read(ctx->db, idmap_tdb_dump_one_entry, data);
    1210 
    1211         if ( ! NT_STATUS_IS_OK(data->ret)) {
    1212                 ret = data->ret;
    1213         }
    1214 
    1215         talloc_free(data);
    1216         return ret;
    1217 }
    1218 
    1219938static struct idmap_methods db_methods = {
    1220 
    1221939        .init = idmap_tdb_db_init,
    1222940        .unixids_to_sids = idmap_tdb_unixids_to_sids,
    1223941        .sids_to_unixids = idmap_tdb_sids_to_unixids,
    1224         .set_mapping = idmap_tdb_set_mapping,
    1225         .remove_mapping = idmap_tdb_remove_mapping,
    1226         .dump_data = idmap_tdb_dump_data,
    1227         .close_fn = idmap_tdb_close
     942        .allocate_id = idmap_tdb_get_new_id,
    1228943};
    1229944
    1230 static struct idmap_alloc_methods db_alloc_methods = {
    1231 
    1232         .init = idmap_tdb_alloc_init,
    1233         .allocate_id = idmap_tdb_allocate_id,
    1234         .get_id_hwm = idmap_tdb_get_hwm,
    1235         .set_id_hwm = idmap_tdb_set_hwm,
    1236         .close_fn = idmap_tdb_alloc_close
    1237 };
    1238 
    1239 NTSTATUS idmap_alloc_tdb_init(void)
    1240 {
    1241         return smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_alloc_methods);
    1242 }
    1243 
    1244945NTSTATUS idmap_tdb_init(void)
    1245946{
    1246         NTSTATUS ret;
    1247 
    1248947        DEBUG(10, ("calling idmap_tdb_init\n"));
    1249948
    1250         /* FIXME: bad hack to actually register also the alloc_tdb module without changining configure.in */
    1251         ret = idmap_alloc_tdb_init();
    1252         if (! NT_STATUS_IS_OK(ret)) {
    1253                 return ret;
    1254         }
    1255949        return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_methods);
    1256950}
Note: See TracChangeset for help on using the changeset viewer.