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_tdb2.c

    r414 r745  
    1515   Copyright (C) Jeremy Allison 2006
    1616   Copyright (C) Simo Sorce 2003-2006
    17    
     17   Copyright (C) Michael Adam 2009-2010
     18
    1819   This program is free software; you can redistribute it and/or modify
    1920   it under the terms of the GNU General Public License as published by
    2021   the Free Software Foundation; either version 2 of the License, or
    2122   (at your option) any later version.
    22    
     23
    2324   This program is distributed in the hope that it will be useful,
    2425   but WITHOUT ANY WARRANTY; without even the implied warranty of
    2526   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2627   GNU General Public License for more details.
    27    
     28
    2829   You should have received a copy of the GNU General Public License
    2930   along with this program; if not, write to the Free Software
     
    3233
    3334#include "includes.h"
     35#include "system/filesys.h"
    3436#include "winbindd.h"
     37#include "idmap.h"
     38#include "idmap_rw.h"
     39#include "dbwrap.h"
     40#include "../libcli/security/dom_sid.h"
     41#include "util_tdb.h"
    3542
    3643#undef DBGC_CLASS
    3744#define DBGC_CLASS DBGC_IDMAP
     45
     46struct idmap_tdb2_context {
     47        struct db_context *db;
     48        const char *script; /* script to provide idmaps */
     49        struct idmap_rw_ops *rw_ops;
     50};
    3851
    3952/* High water mark keys */
     
    4154#define HWM_USER   "USER HWM"
    4255
    43 static struct idmap_tdb2_state {
    44         /* User and group id pool */
    45         uid_t low_uid, high_uid;               /* Range of uids to allocate */
    46         gid_t low_gid, high_gid;               /* Range of gids to allocate */
    47         const char *idmap_script;
    48 } idmap_tdb2_state;
    49 
    50 
    51 
    52 /* handle to the permanent tdb */
    53 static struct db_context *idmap_tdb2;
    54 
    55 static NTSTATUS idmap_tdb2_alloc_load(void);
    56 
    57 static NTSTATUS idmap_tdb2_load_ranges(void)
    58 {
    59         uid_t low_uid = 0;
    60         uid_t high_uid = 0;
    61         gid_t low_gid = 0;
    62         gid_t high_gid = 0;
    63 
    64         if (!lp_idmap_uid(&low_uid, &high_uid)) {
    65                 DEBUG(1, ("idmap uid missing\n"));
    66                 return NT_STATUS_UNSUCCESSFUL;
    67         }
    68 
    69         if (!lp_idmap_gid(&low_gid, &high_gid)) {
    70                 DEBUG(1, ("idmap gid missing\n"));
    71                 return NT_STATUS_UNSUCCESSFUL;
    72         }
    73 
    74         idmap_tdb2_state.low_uid = low_uid;
    75         idmap_tdb2_state.high_uid = high_uid;
    76         idmap_tdb2_state.low_gid = low_gid;
    77         idmap_tdb2_state.high_gid = high_gid;
    78 
    79         if (idmap_tdb2_state.high_uid <= idmap_tdb2_state.low_uid) {
    80                 DEBUG(1, ("idmap uid range missing or invalid\n"));
    81                 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
    82                 return NT_STATUS_UNSUCCESSFUL;
    83         }
    84 
    85         if (idmap_tdb2_state.high_gid <= idmap_tdb2_state.low_gid) {
    86                 DEBUG(1, ("idmap gid range missing or invalid\n"));
    87                 DEBUGADD(1, ("idmap will be unable to map foreign SIDs\n"));
    88                 return NT_STATUS_UNSUCCESSFUL;
     56
     57/*
     58 * check and initialize high/low water marks in the db
     59 */
     60static NTSTATUS idmap_tdb2_init_hwm(struct idmap_domain *dom)
     61{
     62        NTSTATUS status;
     63        uint32 low_id;
     64        struct idmap_tdb2_context *ctx;
     65
     66        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
     67
     68        /* Create high water marks for group and user id */
     69
     70        low_id = dbwrap_fetch_int32(ctx->db, HWM_USER);
     71        if ((low_id == -1) || (low_id < dom->low_id)) {
     72                status = dbwrap_trans_store_int32(ctx->db, HWM_USER,
     73                                                  dom->low_id);
     74                if (!NT_STATUS_IS_OK(status)) {
     75                        DEBUG(0, ("Unable to initialise user hwm in idmap "
     76                                  "database: %s\n", nt_errstr(status)));
     77                        return NT_STATUS_INTERNAL_DB_ERROR;
     78                }
     79        }
     80
     81        low_id = dbwrap_fetch_int32(ctx->db, HWM_GROUP);
     82        if ((low_id == -1) || (low_id < dom->low_id)) {
     83                status = dbwrap_trans_store_int32(ctx->db, HWM_GROUP,
     84                                                  dom->low_id);
     85                if (!NT_STATUS_IS_OK(status)) {
     86                        DEBUG(0, ("Unable to initialise group hwm in idmap "
     87                                  "database: %s\n", nt_errstr(status)));
     88                        return NT_STATUS_INTERNAL_DB_ERROR;
     89                }
    8990        }
    9091
    9192        return NT_STATUS_OK;
    9293}
     94
    9395
    9496/*
    9597  open the permanent tdb
    9698 */
    97 static NTSTATUS idmap_tdb2_open_db(void)
     99static NTSTATUS idmap_tdb2_open_db(struct idmap_domain *dom)
    98100{
    99101        char *db_path;
    100        
    101         if (idmap_tdb2) {
     102        struct idmap_tdb2_context *ctx;
     103
     104        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
     105
     106        if (ctx->db) {
    102107                /* its already open */
    103108                return NT_STATUS_OK;
    104109        }
    105110
    106         db_path = lp_parm_talloc_string(-1, "tdb", "idmap2.tdb", NULL);
    107         if (db_path == NULL) {
    108                 /* fall back to the private directory, which, despite
    109                    its name, is usually on shared storage */
    110                 db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir());
    111         }
     111        db_path = talloc_asprintf(NULL, "%s/idmap2.tdb", lp_private_dir());
    112112        NT_STATUS_HAVE_NO_MEMORY(db_path);
    113113
    114114        /* Open idmap repository */
    115         idmap_tdb2 = db_open(NULL, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644);
     115        ctx->db = db_open(ctx, db_path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644);
    116116        TALLOC_FREE(db_path);
    117117
    118         if (idmap_tdb2 == NULL) {
     118        if (ctx->db == NULL) {
    119119                DEBUG(0, ("Unable to open idmap_tdb2 database '%s'\n",
    120120                          db_path));
     
    122122        }
    123123
    124         /* load the ranges and high/low water marks */
    125         return idmap_tdb2_alloc_load();
    126 }
    127 
    128 
    129 /*
    130   load the idmap allocation ranges and high/low water marks
    131 */
    132 static NTSTATUS idmap_tdb2_alloc_load(void)
    133 {
    134         NTSTATUS status;
    135         uint32 low_id;
    136 
    137         /* see if a idmap script is configured */
    138         idmap_tdb2_state.idmap_script = lp_parm_const_string(-1, "idmap",
    139                                                              "script", NULL);
    140 
    141         if (idmap_tdb2_state.idmap_script) {
    142                 DEBUG(1, ("using idmap script '%s'\n",
    143                           idmap_tdb2_state.idmap_script));
    144         }
    145 
    146         /* load ranges */
    147 
    148         status = idmap_tdb2_load_ranges();
    149         if (!NT_STATUS_IS_OK(status)) {
    150                 return status;
    151         }
    152 
    153         /* Create high water marks for group and user id */
    154 
    155         low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_USER);
    156         if ((low_id == -1) || (low_id < idmap_tdb2_state.low_uid)) {
    157                 if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32(
    158                                              idmap_tdb2, HWM_USER,
    159                                              idmap_tdb2_state.low_uid))) {
    160                         DEBUG(0, ("Unable to initialise user hwm in idmap "
    161                                   "database\n"));
    162                         return NT_STATUS_INTERNAL_DB_ERROR;
    163                 }
    164         }
    165 
    166         low_id = dbwrap_fetch_int32(idmap_tdb2, HWM_GROUP);
    167         if ((low_id == -1) || (low_id < idmap_tdb2_state.low_gid)) {
    168                 if (!NT_STATUS_IS_OK(dbwrap_trans_store_int32(
    169                                              idmap_tdb2, HWM_GROUP,
    170                                              idmap_tdb2_state.low_gid))) {
    171                         DEBUG(0, ("Unable to initialise group hwm in idmap "
    172                                   "database\n"));
    173                         return NT_STATUS_INTERNAL_DB_ERROR;
    174                 }
    175         }
    176 
    177         return NT_STATUS_OK;
    178 }
    179 
    180 
    181 /*
    182   Initialise idmap alloc database.
    183 */
    184 static NTSTATUS idmap_tdb2_alloc_init(const char *params)
    185 {
    186         /* nothing to do - we want to avoid opening the permanent
    187            database if possible. Instead we load the params when we
    188            first need it. */
    189         return NT_STATUS_OK;
     124        return idmap_tdb2_init_hwm(dom);
    190125}
    191126
     
    248183}
    249184
    250 static NTSTATUS idmap_tdb2_allocate_id(struct unixid *xid)
     185static NTSTATUS idmap_tdb2_allocate_id(struct idmap_domain *dom,
     186                                       struct unixid *xid)
    251187{
    252188        const char *hwmkey;
     
    256192        NTSTATUS status;
    257193        struct idmap_tdb2_allocate_id_context state;
    258 
    259         status = idmap_tdb2_open_db();
     194        struct idmap_tdb2_context *ctx;
     195
     196        status = idmap_tdb2_open_db(dom);
    260197        NT_STATUS_NOT_OK_RETURN(status);
     198
     199        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
    261200
    262201        /* Get current high water mark */
     
    266205                hwmkey = HWM_USER;
    267206                hwmtype = "UID";
    268                 high_hwm = idmap_tdb2_state.high_uid;
    269207                break;
    270208
     
    272210                hwmkey = HWM_GROUP;
    273211                hwmtype = "GID";
    274                 high_hwm = idmap_tdb2_state.high_gid;
    275212                break;
    276213
     
    279216                return NT_STATUS_INVALID_PARAMETER;
    280217        }
     218
     219        high_hwm = dom->high_id;
    281220
    282221        state.hwm = hwm;
     
    285224        state.hwmkey = hwmkey;
    286225
    287         status = dbwrap_trans_do(idmap_tdb2, idmap_tdb2_allocate_id_action,
     226        status = dbwrap_trans_do(ctx->db, idmap_tdb2_allocate_id_action,
    288227                                 &state);
    289228
    290229        if (NT_STATUS_IS_OK(status)) {
    291230                xid->id = state.hwm;
    292                 DEBUG(10,("New %s = %d\n", hwmtype, hwm));
     231                DEBUG(10,("New %s = %d\n", hwmtype, state.hwm));
    293232        } else {
    294233                DEBUG(1, ("Error allocating a new %s\n", hwmtype));
     
    298237}
    299238
    300 /*
    301   Get current highest id.
    302 */
    303 static NTSTATUS idmap_tdb2_get_hwm(struct unixid *xid)
    304 {
    305         const char *hwmkey;
    306         const char *hwmtype;
    307         uint32_t hwm;
    308         uint32_t high_hwm;
    309         NTSTATUS status;
    310 
    311         status = idmap_tdb2_open_db();
    312         NT_STATUS_NOT_OK_RETURN(status);
    313 
    314         /* Get current high water mark */
    315         switch (xid->type) {
    316 
    317         case ID_TYPE_UID:
    318                 hwmkey = HWM_USER;
    319                 hwmtype = "UID";
    320                 high_hwm = idmap_tdb2_state.high_uid;
    321                 break;
    322 
    323         case ID_TYPE_GID:
    324                 hwmkey = HWM_GROUP;
    325                 hwmtype = "GID";
    326                 high_hwm = idmap_tdb2_state.high_gid;
    327                 break;
    328 
    329         default:
    330                 return NT_STATUS_INVALID_PARAMETER;
    331         }
    332 
    333         if ((hwm = dbwrap_fetch_int32(idmap_tdb2, hwmkey)) == -1) {
    334                 return NT_STATUS_INTERNAL_DB_ERROR;
    335         }
    336 
    337         xid->id = hwm;
    338 
    339         /* Warn if it is out of range */
    340         if (hwm >= high_hwm) {
    341                 DEBUG(0, ("Warning: %s range full!! (max: %lu)\n",
    342                           hwmtype, (unsigned long)high_hwm));
    343         }
    344 
    345         return NT_STATUS_OK;
    346 }
    347 
    348 /*
    349   Set high id.
    350 */
    351 static NTSTATUS idmap_tdb2_set_hwm(struct unixid *xid)
    352 {
    353         /* not supported, or we would invalidate the cache tdb on
    354            other nodes */
    355         DEBUG(0,("idmap_tdb2_set_hwm not supported\n"));
    356         return NT_STATUS_NOT_SUPPORTED;
    357 }
    358 
    359 /*
    360   Close the alloc tdb
    361 */
    362 static NTSTATUS idmap_tdb2_alloc_close(void)
    363 {
    364         /* don't actually close it */
    365         return NT_STATUS_OK;
     239/**
     240 * Allocate a new unix-ID.
     241 * For now this is for the default idmap domain only.
     242 * Should be extended later on.
     243 */
     244static NTSTATUS idmap_tdb2_get_new_id(struct idmap_domain *dom,
     245                                      struct unixid *id)
     246{
     247        NTSTATUS ret;
     248
     249        if (!strequal(dom->name, "*")) {
     250                DEBUG(3, ("idmap_tdb2_get_new_id: "
     251                          "Refusing creation of mapping for domain'%s'. "
     252                          "Currently only supported for the default "
     253                          "domain \"*\".\n",
     254                           dom->name));
     255                return NT_STATUS_NOT_IMPLEMENTED;
     256        }
     257
     258        ret = idmap_tdb2_allocate_id(dom, id);
     259
     260        return ret;
    366261}
    367262
     
    369264  IDMAP MAPPING TDB BACKEND
    370265*/
    371 struct idmap_tdb2_context {
    372         uint32_t filter_low_id;
    373         uint32_t filter_high_id;
    374 };
     266
     267static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom,
     268                                       const struct id_map *map);
    375269
    376270/*
    377271  Initialise idmap database.
    378272*/
    379 static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom,
    380                                    const char *params)
     273static NTSTATUS idmap_tdb2_db_init(struct idmap_domain *dom)
    381274{
    382275        NTSTATUS ret;
    383276        struct idmap_tdb2_context *ctx;
    384         NTSTATUS status;
    385 
    386         status = idmap_tdb2_open_db();
    387         NT_STATUS_NOT_OK_RETURN(status);
    388 
    389         ctx = talloc(dom, struct idmap_tdb2_context);
     277        char *config_option = NULL;
     278        const char * idmap_script = NULL;
     279
     280        ctx = talloc_zero(dom, struct idmap_tdb2_context);
    390281        if ( ! ctx) {
    391282                DEBUG(0, ("Out of memory!\n"));
     
    393284        }
    394285
    395         if (strequal(dom->name, "*")) {
    396                 uid_t low_uid = 0;
    397                 uid_t high_uid = 0;
    398                 gid_t low_gid = 0;
    399                 gid_t high_gid = 0;
    400 
    401                 ctx->filter_low_id = 0;
    402                 ctx->filter_high_id = 0;
    403 
    404                 if (lp_idmap_uid(&low_uid, &high_uid)) {
    405                         ctx->filter_low_id = low_uid;
    406                         ctx->filter_high_id = high_uid;
    407                 } else {
    408                         DEBUG(3, ("Warning: 'idmap uid' not set!\n"));
    409                 }
    410 
    411                 if (lp_idmap_gid(&low_gid, &high_gid)) {
    412                         if ((low_gid != low_uid) || (high_gid != high_uid)) {
    413                                 DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
    414                                       " ranges do not agree -- building "
    415                                       "intersection\n"));
    416                                 ctx->filter_low_id = MAX(ctx->filter_low_id,
    417                                                          low_gid);
    418                                 ctx->filter_high_id = MIN(ctx->filter_high_id,
    419                                                           high_gid);
    420                         }
    421                 } else {
    422                         DEBUG(3, ("Warning: 'idmap gid' not set!\n"));
    423                 }
    424         } else {
    425                 char *config_option = NULL;
    426                 const char *range;
    427                 config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
    428                 if ( ! config_option) {
    429                         DEBUG(0, ("Out of memory!\n"));
    430                         ret = NT_STATUS_NO_MEMORY;
    431                         goto failed;
    432                 }
    433 
    434                 range = lp_parm_const_string(-1, config_option, "range", NULL);
    435                 if (( ! range) ||
    436                     (sscanf(range, "%u - %u", &ctx->filter_low_id, &ctx->filter_high_id) != 2))
    437                 {
    438                         ctx->filter_low_id = 0;
    439                         ctx->filter_high_id = 0;
    440                 }
    441 
    442                 talloc_free(config_option);
    443         }
    444 
    445         if (ctx->filter_low_id > ctx->filter_high_id) {
    446                 ctx->filter_low_id = 0;
    447                 ctx->filter_high_id = 0;
    448         }
     286        config_option = talloc_asprintf(ctx, "idmap config %s", dom->name);
     287        if (config_option == NULL) {
     288                DEBUG(0, ("Out of memory!\n"));
     289                ret = NT_STATUS_NO_MEMORY;
     290                goto failed;
     291        }
     292        ctx->script = lp_parm_const_string(-1, config_option, "script", "NULL");
     293        talloc_free(config_option);
     294
     295        idmap_script = lp_parm_const_string(-1, "idmap", "script", NULL);
     296        if (idmap_script != NULL) {
     297                DEBUG(0, ("Warning: 'idmap:script' is deprecated. "
     298                          " Please use 'idmap config * : script' instead!\n"));
     299        }
     300
     301        if (strequal(dom->name, "*") && ctx->script == NULL) {
     302                /* fall back to idmap:script for backwards compatibility */
     303                ctx->script = idmap_script;
     304        }
     305
     306        if (ctx->script) {
     307                DEBUG(1, ("using idmap script '%s'\n", ctx->script));
     308        }
     309
     310        ctx->rw_ops = talloc_zero(ctx, struct idmap_rw_ops);
     311        if (ctx->rw_ops == NULL) {
     312                DEBUG(0, ("Out of memory!\n"));
     313                ret = NT_STATUS_NO_MEMORY;
     314                goto failed;
     315        }
     316
     317        ctx->rw_ops->get_new_id = idmap_tdb2_get_new_id;
     318        ctx->rw_ops->set_mapping = idmap_tdb2_set_mapping;
    449319
    450320        dom->private_data = ctx;
     321
     322        ret = idmap_tdb2_open_db(dom);
     323        if (!NT_STATUS_IS_OK(ret)) {
     324                goto failed;
     325        }
    451326
    452327        return NT_STATUS_OK;
     
    456331        return ret;
    457332}
     333
     334
     335/**
     336 * store a mapping in the database.
     337 */
    458338
    459339struct idmap_tdb2_set_mapping_context {
     
    503383done:
    504384        talloc_free(tmp_ctx);
     385        return ret;
     386}
     387
     388static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map)
     389{
     390        struct idmap_tdb2_context *ctx;
     391        NTSTATUS ret;
     392        char *ksidstr, *kidstr;
     393        struct idmap_tdb2_set_mapping_context state;
     394
     395        if (!map || !map->sid) {
     396                return NT_STATUS_INVALID_PARAMETER;
     397        }
     398
     399        ksidstr = kidstr = NULL;
     400
     401        /* TODO: should we filter a set_mapping using low/high filters ? */
     402
     403        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
     404
     405        switch (map->xid.type) {
     406
     407        case ID_TYPE_UID:
     408                kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
     409                break;
     410
     411        case ID_TYPE_GID:
     412                kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
     413                break;
     414
     415        default:
     416                DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
     417                return NT_STATUS_INVALID_PARAMETER;
     418        }
     419
     420        if (kidstr == NULL) {
     421                DEBUG(0, ("ERROR: Out of memory!\n"));
     422                ret = NT_STATUS_NO_MEMORY;
     423                goto done;
     424        }
     425
     426        ksidstr = sid_string_talloc(ctx, map->sid);
     427        if (ksidstr == NULL) {
     428                DEBUG(0, ("Out of memory!\n"));
     429                ret = NT_STATUS_NO_MEMORY;
     430                goto done;
     431        }
     432
     433        state.ksidstr = ksidstr;
     434        state.kidstr = kidstr;
     435
     436        ret = dbwrap_trans_do(ctx->db, idmap_tdb2_set_mapping_action,
     437                              &state);
     438
     439done:
     440        talloc_free(ksidstr);
     441        talloc_free(kidstr);
     442        return ret;
     443}
     444
     445/**
     446 * Create a new mapping for an unmapped SID, also allocating a new ID.
     447 * This should be run inside a transaction.
     448 *
     449 * TODO:
     450*  Properly integrate this with multi domain idmap config:
     451 * Currently, the allocator is default-config only.
     452 */
     453static NTSTATUS idmap_tdb2_new_mapping(struct idmap_domain *dom, struct id_map *map)
     454{
     455        NTSTATUS ret;
     456        struct idmap_tdb2_context *ctx;
     457
     458        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
     459
     460        ret = idmap_rw_new_mapping(dom, ctx->rw_ops, map);
     461
    505462        return ret;
    506463}
     
    531488        unsigned long v;
    532489
    533         cmd = talloc_asprintf(ctx, "%s ", idmap_tdb2_state.idmap_script);
     490        cmd = talloc_asprintf(ctx, "%s ", ctx->script);
    534491        NT_STATUS_HAVE_NO_MEMORY(cmd); 
    535492
     
    562519                if (!string_to_sid(map->sid, &line[4])) {
    563520                        DEBUG(0,("Bad SID in '%s' from idmap script %s\n",
    564                                  line, idmap_tdb2_state.idmap_script));
     521                                 line, ctx->script));
    565522                        return NT_STATUS_NONE_MAPPED;                   
    566523                }
    567524        } else {
    568525                DEBUG(0,("Bad reply '%s' from idmap script %s\n",
    569                          line, idmap_tdb2_state.idmap_script));
     526                         line, ctx->script));
    570527                return NT_STATUS_NONE_MAPPED;
    571528        }
     
    579536  Single id to sid lookup function.
    580537*/
    581 static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_tdb2_context *ctx, struct id_map *map)
     538static NTSTATUS idmap_tdb2_id_to_sid(struct idmap_domain *dom, struct id_map *map)
    582539{
    583540        NTSTATUS ret;
     
    585542        char *keystr;
    586543        NTSTATUS status;
    587 
    588         status = idmap_tdb2_open_db();
     544        struct idmap_tdb2_context *ctx;
     545
     546
     547        if (!dom || !map) {
     548                return NT_STATUS_INVALID_PARAMETER;
     549        }
     550
     551        status = idmap_tdb2_open_db(dom);
    589552        NT_STATUS_NOT_OK_RETURN(status);
    590553
    591         if (!ctx || !map) {
    592                 return NT_STATUS_INVALID_PARAMETER;
    593         }
     554        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
    594555
    595556        /* apply filters before checking */
    596         if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
    597             (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
     557        if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
    598558                DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
    599                                 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
     559                                map->xid.id, dom->low_id, dom->high_id));
    600560                return NT_STATUS_NONE_MAPPED;
    601561        }
     
    606566                keystr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
    607567                break;
    608                
     568
    609569        case ID_TYPE_GID:
    610570                keystr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
     
    616576        }
    617577
    618         /* final SAFE_FREE safe */
    619         data.dptr = NULL;
    620 
    621578        if (keystr == NULL) {
    622579                DEBUG(0, ("Out of memory!\n"));
     
    628585
    629586        /* Check if the mapping exists */
    630         data = dbwrap_fetch_bystring(idmap_tdb2, keystr, keystr);
     587        data = dbwrap_fetch_bystring(ctx->db, keystr, keystr);
    631588
    632589        if (!data.dptr) {
     
    635592
    636593                DEBUG(10,("Record %s not found\n", keystr));
    637                 if (idmap_tdb2_state.idmap_script == NULL) {
     594                if (ctx->script == NULL) {
    638595                        ret = NT_STATUS_NONE_MAPPED;
    639596                        goto done;
     
    641598
    642599                ret = idmap_tdb2_script(ctx, map, "IDTOSID %s", keystr);
    643 
    644                 /* store it on shared storage */
    645600                if (!NT_STATUS_IS_OK(ret)) {
    646601                        goto done;
     
    656611                store_state.kidstr = keystr;
    657612
    658                 ret = dbwrap_trans_do(idmap_tdb2, idmap_tdb2_set_mapping_action,
     613                ret = dbwrap_trans_do(ctx->db, idmap_tdb2_set_mapping_action,
    659614                                      &store_state);
    660615                goto done;
    661616        }
    662                
     617
    663618        if (!string_to_sid(map->sid, (const char *)data.dptr)) {
    664619                DEBUG(10,("INVALID SID (%s) in record %s\n",
     
    680635 Single sid to id lookup function.
    681636*/
    682 static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_tdb2_context *ctx, struct id_map *map)
     637static NTSTATUS idmap_tdb2_sid_to_id(struct idmap_domain *dom, struct id_map *map)
    683638{
    684639        NTSTATUS ret;
     
    686641        char *keystr;
    687642        unsigned long rec_id = 0;
     643        struct idmap_tdb2_context *ctx;
    688644        TALLOC_CTX *tmp_ctx = talloc_stackframe();
    689645
    690         ret = idmap_tdb2_open_db();
     646        ret = idmap_tdb2_open_db(dom);
    691647        NT_STATUS_NOT_OK_RETURN(ret);
     648
     649        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
    692650
    693651        keystr = sid_string_talloc(tmp_ctx, map->sid);
     
    701659
    702660        /* Check if sid is present in database */
    703         data = dbwrap_fetch_bystring(idmap_tdb2, tmp_ctx, keystr);
     661        data = dbwrap_fetch_bystring(ctx->db, tmp_ctx, keystr);
    704662        if (!data.dptr) {
    705663                char *idstr;
     
    708666                DEBUG(10,(__location__ " Record %s not found\n", keystr));
    709667
    710                 if (idmap_tdb2_state.idmap_script == NULL) {
     668                if (ctx->script == NULL) {
    711669                        ret = NT_STATUS_NONE_MAPPED;
    712670                        goto done;
    713671                }
    714                        
     672
    715673                ret = idmap_tdb2_script(ctx, map, "SIDTOID %s", keystr);
    716                 /* store it on shared storage */
    717674                if (!NT_STATUS_IS_OK(ret)) {
     675                        goto done;
     676                }
     677
     678                /* apply filters before returning result */
     679                if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
     680                        DEBUG(5, ("Script returned id (%u) out of range "
     681                                  "(%u - %u). Filtered!\n",
     682                                  map->xid.id, dom->low_id, dom->high_id));
     683                        ret = NT_STATUS_NONE_MAPPED;
    718684                        goto done;
    719685                }
     
    730696                store_state.kidstr = idstr;
    731697
    732                 ret = dbwrap_trans_do(idmap_tdb2, idmap_tdb2_set_mapping_action,
     698                ret = dbwrap_trans_do(ctx->db, idmap_tdb2_set_mapping_action,
    733699                                      &store_state);
    734700                goto done;
     
    751717                DEBUG(2, ("Found INVALID record %s -> %s\n", keystr, (const char *)data.dptr));
    752718                ret = NT_STATUS_INTERNAL_DB_ERROR;
    753         }
    754        
     719                goto done;
     720        }
     721
    755722        /* apply filters before returning result */
    756         if ((ctx->filter_low_id && (map->xid.id < ctx->filter_low_id)) ||
    757             (ctx->filter_high_id && (map->xid.id > ctx->filter_high_id))) {
     723        if (!idmap_unix_id_is_in_range(map->xid.id, dom)) {
    758724                DEBUG(5, ("Requested id (%u) out of range (%u - %u). Filtered!\n",
    759                                 map->xid.id, ctx->filter_low_id, ctx->filter_high_id));
     725                                map->xid.id, dom->low_id, dom->high_id));
    760726                ret = NT_STATUS_NONE_MAPPED;
    761727        }
     
    771737static NTSTATUS idmap_tdb2_unixids_to_sids(struct idmap_domain *dom, struct id_map **ids)
    772738{
    773         struct idmap_tdb2_context *ctx;
    774739        NTSTATUS ret;
    775740        int i;
     
    779744                ids[i]->status = ID_UNKNOWN;
    780745        }
    781        
    782         ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
    783746
    784747        for (i = 0; ids[i]; i++) {
    785                 ret = idmap_tdb2_id_to_sid(ctx, ids[i]);
     748                ret = idmap_tdb2_id_to_sid(dom, ids[i]);
    786749                if ( ! NT_STATUS_IS_OK(ret)) {
    787750
     
    793756                                continue;
    794757                        }
    795                        
     758
    796759                        /* some fatal error occurred, return immediately */
    797760                        goto done;
     
    811774  lookup a set of sids.
    812775*/
     776
     777struct idmap_tdb2_sids_to_unixids_context {
     778        struct idmap_domain *dom;
     779        struct id_map **ids;
     780        bool allocate_unmapped;
     781};
     782
     783static NTSTATUS idmap_tdb2_sids_to_unixids_action(struct db_context *db,
     784                                                  void *private_data)
     785{
     786        struct idmap_tdb2_sids_to_unixids_context *state;
     787        int i;
     788        NTSTATUS ret = NT_STATUS_OK;
     789
     790        state = (struct idmap_tdb2_sids_to_unixids_context *)private_data;
     791
     792        DEBUG(10, ("idmap_tdb2_sids_to_unixids_action: "
     793                   " domain: [%s], allocate: %s\n",
     794                   state->dom->name,
     795                   state->allocate_unmapped ? "yes" : "no"));
     796
     797        for (i = 0; state->ids[i]; i++) {
     798                if ((state->ids[i]->status == ID_UNKNOWN) ||
     799                    /* retry if we could not map in previous run: */
     800                    (state->ids[i]->status == ID_UNMAPPED))
     801                {
     802                        NTSTATUS ret2;
     803
     804                        ret2 = idmap_tdb2_sid_to_id(state->dom, state->ids[i]);
     805                        if (!NT_STATUS_IS_OK(ret2)) {
     806
     807                                /* if it is just a failed mapping, continue */
     808                                if (NT_STATUS_EQUAL(ret2, NT_STATUS_NONE_MAPPED)) {
     809
     810                                        /* make sure it is marked as unmapped */
     811                                        state->ids[i]->status = ID_UNMAPPED;
     812                                        ret = STATUS_SOME_UNMAPPED;
     813                                } else {
     814                                        /* some fatal error occurred, return immediately */
     815                                        ret = ret2;
     816                                        goto done;
     817                                }
     818                        } else {
     819                                /* all ok, id is mapped */
     820                                state->ids[i]->status = ID_MAPPED;
     821                        }
     822                }
     823
     824                if ((state->ids[i]->status == ID_UNMAPPED) &&
     825                    state->allocate_unmapped)
     826                {
     827                        ret = idmap_tdb2_new_mapping(state->dom, state->ids[i]);
     828                        if (!NT_STATUS_IS_OK(ret)) {
     829                                goto done;
     830                        }
     831                }
     832        }
     833
     834done:
     835        return ret;
     836}
     837
    813838static NTSTATUS idmap_tdb2_sids_to_unixids(struct idmap_domain *dom, struct id_map **ids)
    814839{
     840        NTSTATUS ret;
     841        int i;
     842        struct idmap_tdb2_sids_to_unixids_context state;
    815843        struct idmap_tdb2_context *ctx;
    816         NTSTATUS ret;
    817         int i;
     844
     845        ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
    818846
    819847        /* initialize the status to avoid suprise */
     
    821849                ids[i]->status = ID_UNKNOWN;
    822850        }
    823        
    824         ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
    825 
    826         for (i = 0; ids[i]; i++) {
    827                 ret = idmap_tdb2_sid_to_id(ctx, ids[i]);
    828                 if ( ! NT_STATUS_IS_OK(ret)) {
    829 
    830                         /* if it is just a failed mapping continue */
    831                         if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
    832 
    833                                 /* make sure it is marked as unmapped */
    834                                 ids[i]->status = ID_UNMAPPED;
    835                                 continue;
    836                         }
    837                        
    838                         /* some fatal error occurred, return immediately */
    839                         goto done;
    840                 }
    841 
    842                 /* all ok, id is mapped */
    843                 ids[i]->status = ID_MAPPED;
    844         }
    845 
    846         ret = NT_STATUS_OK;
    847 
    848 done:
    849         return ret;
    850 }
    851 
    852 
    853 /*
    854   set a mapping.
    855 */
    856 
    857 static NTSTATUS idmap_tdb2_set_mapping(struct idmap_domain *dom, const struct id_map *map)
    858 {
    859         struct idmap_tdb2_context *ctx;
    860         NTSTATUS ret;
    861         char *ksidstr, *kidstr;
    862         struct idmap_tdb2_set_mapping_context state;
    863 
    864         if (!map || !map->sid) {
    865                 return NT_STATUS_INVALID_PARAMETER;
    866         }
    867 
    868         ksidstr = kidstr = NULL;
    869 
    870         /* TODO: should we filter a set_mapping using low/high filters ? */
    871        
    872         ctx = talloc_get_type(dom->private_data, struct idmap_tdb2_context);
    873 
    874         switch (map->xid.type) {
    875 
    876         case ID_TYPE_UID:
    877                 kidstr = talloc_asprintf(ctx, "UID %lu", (unsigned long)map->xid.id);
    878                 break;
    879                
    880         case ID_TYPE_GID:
    881                 kidstr = talloc_asprintf(ctx, "GID %lu", (unsigned long)map->xid.id);
    882                 break;
    883 
    884         default:
    885                 DEBUG(2, ("INVALID unix ID type: 0x02%x\n", map->xid.type));
    886                 return NT_STATUS_INVALID_PARAMETER;
    887         }
    888 
    889         if (kidstr == NULL) {
    890                 DEBUG(0, ("ERROR: Out of memory!\n"));
    891                 ret = NT_STATUS_NO_MEMORY;
    892                 goto done;
    893         }
    894 
    895         if (!(ksidstr = sid_string_talloc(ctx, map->sid))) {
    896                 DEBUG(0, ("Out of memory!\n"));
    897                 ret = NT_STATUS_NO_MEMORY;
    898                 goto done;
    899         }
    900 
    901         state.ksidstr = ksidstr;
    902         state.kidstr = kidstr;
    903 
    904         ret = dbwrap_trans_do(idmap_tdb2, idmap_tdb2_set_mapping_action,
    905                               &state);
    906 
    907 done:
    908         talloc_free(ksidstr);
    909         talloc_free(kidstr);
    910         return ret;
    911 }
    912 
    913 /*
    914   remove a mapping.
    915 */
    916 static NTSTATUS idmap_tdb2_remove_mapping(struct idmap_domain *dom, const struct id_map *map)
    917 {
    918         /* not supported as it would invalidate the cache tdb on other
    919            nodes */
    920         DEBUG(0,("idmap_tdb2_remove_mapping not supported\n"));
    921         return NT_STATUS_NOT_SUPPORTED;
    922 }
    923 
    924 /*
    925   Close the idmap tdb instance
    926 */
    927 static NTSTATUS idmap_tdb2_close(struct idmap_domain *dom)
    928 {
    929         /* don't do anything */
    930         return NT_STATUS_OK;
    931 }
    932 
    933 
    934 /*
    935   Dump all mappings out
    936 */
    937 static NTSTATUS idmap_tdb2_dump_data(struct idmap_domain *dom, struct id_map **maps, int *num_maps)
    938 {
    939         DEBUG(0,("idmap_tdb2_dump_data not supported\n"));
    940         return NT_STATUS_NOT_SUPPORTED;
    941 }
     851
     852        state.dom = dom;
     853        state.ids = ids;
     854        state.allocate_unmapped = false;
     855
     856        ret = idmap_tdb2_sids_to_unixids_action(ctx->db, &state);
     857
     858        if (NT_STATUS_EQUAL(ret, STATUS_SOME_UNMAPPED) && !dom->read_only) {
     859                state.allocate_unmapped = true;
     860                ret = dbwrap_trans_do(ctx->db,
     861                                      idmap_tdb2_sids_to_unixids_action,
     862                                      &state);
     863        }
     864
     865        return ret;
     866}
     867
    942868
    943869static struct idmap_methods db_methods = {
     
    945871        .unixids_to_sids = idmap_tdb2_unixids_to_sids,
    946872        .sids_to_unixids = idmap_tdb2_sids_to_unixids,
    947         .set_mapping     = idmap_tdb2_set_mapping,
    948         .remove_mapping  = idmap_tdb2_remove_mapping,
    949         .dump_data       = idmap_tdb2_dump_data,
    950         .close_fn        = idmap_tdb2_close
     873        .allocate_id     = idmap_tdb2_get_new_id
    951874};
    952875
    953 static struct idmap_alloc_methods db_alloc_methods = {
    954         .init        = idmap_tdb2_alloc_init,
    955         .allocate_id = idmap_tdb2_allocate_id,
    956         .get_id_hwm  = idmap_tdb2_get_hwm,
    957         .set_id_hwm  = idmap_tdb2_set_hwm,
    958         .close_fn    = idmap_tdb2_alloc_close
    959 };
    960 
    961876NTSTATUS idmap_tdb2_init(void)
    962877{
    963         NTSTATUS ret;
    964 
    965         /* register both backends */
    966         ret = smb_register_idmap_alloc(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_alloc_methods);
    967         if (! NT_STATUS_IS_OK(ret)) {
    968                 DEBUG(0, ("Unable to register idmap alloc tdb2 module: %s\n", get_friendly_nt_error_msg(ret)));
    969                 return ret;
    970         }
    971 
    972878        return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb2", &db_methods);
    973879}
Note: See TracChangeset for help on using the changeset viewer.