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

    r596 r745  
    66   Copyright (C) Simo Sorce 2003-2007
    77   Copyright (C) Jeremy Allison 2006
     8   Copyright (C) Michael Adam 2010
    89
    910   This program is free software; you can redistribute it and/or modify
     
    2324#include "includes.h"
    2425#include "winbindd.h"
     26#include "idmap.h"
     27#include "passdb/machine_sid.h"
    2528
    2629#undef DBGC_CLASS
     
    2831
    2932static_decl_idmap;
     33
     34static void idmap_init(void)
     35{
     36        static bool initialized;
     37
     38        if (initialized) {
     39                return;
     40        }
     41
     42        DEBUG(10, ("idmap_init(): calling static_init_idmap\n"));
     43
     44        static_init_idmap;
     45
     46        initialized = true;
     47}
    3048
    3149/**
     
    4260
    4361/**
    44  * Pointer to the alloc backend methods. Modules register themselves here via
    45  * smb_register_idmap_alloc.
    46  */
    47 struct idmap_alloc_backend {
    48         const char *name;
    49         struct idmap_alloc_methods *methods;
    50         struct idmap_alloc_backend *prev, *next;
    51 };
    52 static struct idmap_alloc_backend *alloc_backends = NULL;
    53 
    54 /**
    55  * The idmap alloc context that is configured via "idmap alloc
    56  * backend". Defaults to "idmap backend" in case the module (tdb, ldap) also
    57  * provides alloc methods.
    58  */
    59 struct idmap_alloc_context {
    60         struct idmap_alloc_methods *methods;
    61 };
    62 static struct idmap_alloc_context *idmap_alloc_ctx = NULL;
    63 
    64 /**
    6562 * Default idmap domain configured via "idmap backend".
    6663 */
     
    8784
    8885        for (b = backends; b; b = b->next) {
    89                 if (strequal(b->name, name)) {
    90                         return b->methods;
    91                 }
    92         }
    93 
    94         return NULL;
    95 }
    96 
    97 static struct idmap_alloc_methods *get_alloc_methods(const char *name)
    98 {
    99         struct idmap_alloc_backend *b;
    100 
    101         for (b = alloc_backends; b; b = b->next) {
    10286                if (strequal(b->name, name)) {
    10387                        return b->methods;
     
    171155}
    172156
    173 /**********************************************************************
    174  Allow a module to register itself as an alloc method.
    175 **********************************************************************/
    176 
    177 NTSTATUS smb_register_idmap_alloc(int version, const char *name,
    178                                   struct idmap_alloc_methods *methods)
    179 {
    180         struct idmap_alloc_methods *test;
    181         struct idmap_alloc_backend *entry;
    182 
    183         if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
    184                 DEBUG(0, ("Failed to register idmap alloc module.\n"
    185                           "The module was compiled against "
    186                           "SMB_IDMAP_INTERFACE_VERSION %d,\n"
    187                           "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
    188                           "Please recompile against the current version "
    189                           "of samba!\n",
    190                           version, SMB_IDMAP_INTERFACE_VERSION));
    191                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
    192         }
    193 
    194         if (!name || !name[0] || !methods) {
    195                 DEBUG(0,("Called with NULL pointer or empty name!\n"));
    196                 return NT_STATUS_INVALID_PARAMETER;
    197         }
    198 
    199         test = get_alloc_methods(name);
    200         if (test) {
    201                 DEBUG(0,("idmap_alloc module %s already registered!\n", name));
    202                 return NT_STATUS_OBJECT_NAME_COLLISION;
    203         }
    204 
    205         entry = talloc(NULL, struct idmap_alloc_backend);
    206         if ( ! entry) {
    207                 DEBUG(0,("Out of memory!\n"));
    208                 return NT_STATUS_NO_MEMORY;
    209         }
    210         entry->name = talloc_strdup(entry, name);
    211         if ( ! entry->name) {
    212                 DEBUG(0,("Out of memory!\n"));
    213                 return NT_STATUS_NO_MEMORY;
    214         }
    215         entry->methods = methods;
    216 
    217         DLIST_ADD(alloc_backends, entry);
    218         DEBUG(5, ("Successfully added idmap alloc backend '%s'\n", name));
    219         return NT_STATUS_OK;
    220 }
    221 
    222 static int close_domain_destructor(struct idmap_domain *dom)
    223 {
    224         NTSTATUS ret;
    225 
    226         ret = dom->methods->close_fn(dom);
    227         if (!NT_STATUS_IS_OK(ret)) {
    228                 DEBUG(3, ("Failed to close idmap domain [%s]!\n", dom->name));
    229         }
    230 
    231         return 0;
    232 }
    233 
    234 static bool parse_idmap_module(TALLOC_CTX *mem_ctx, const char *param,
    235                                char **pmodulename, char **pargs)
    236 {
    237         char *modulename;
    238         char *args;
    239 
    240         if (strncmp(param, "idmap_", 6) == 0) {
    241                 param += 6;
    242                 DEBUG(1, ("idmap_init: idmap backend uses deprecated "
    243                           "'idmap_' prefix.  Please replace 'idmap_%s' by "
    244                           "'%s'\n", param, param));
    245         }
    246 
    247         modulename = talloc_strdup(mem_ctx, param);
    248         if (modulename == NULL) {
    249                 return false;
    250         }
    251 
    252         args = strchr(modulename, ':');
    253         if (args == NULL) {
    254                 *pmodulename = modulename;
    255                 *pargs = NULL;
    256                 return true;
    257         }
    258 
    259         *args = '\0';
    260 
    261         args = talloc_strdup(mem_ctx, args+1);
    262         if (args == NULL) {
    263                 TALLOC_FREE(modulename);
    264                 return false;
    265         }
    266 
    267         *pmodulename = modulename;
    268         *pargs = args;
    269         return true;
    270 }
    271 
    272157/**
    273158 * Initialize a domain structure
     
    275160 * @param[in] domainname        which domain is this for
    276161 * @param[in] modulename        which backend module
    277  * @param[in] params            parameter to pass to the init function
     162 * @param[in] check_range       whether range checking should be done
    278163 * @result The initialized structure
    279164 */
     
    281166                                              const char *domainname,
    282167                                              const char *modulename,
    283                                               const char *params)
     168                                              bool check_range)
    284169{
    285170        struct idmap_domain *result;
    286171        NTSTATUS status;
     172        char *config_option = NULL;
     173        const char *range;
    287174
    288175        result = talloc_zero(mem_ctx, struct idmap_domain);
     
    296183                DEBUG(0, ("talloc failed\n"));
    297184                goto fail;
     185        }
     186
     187        /*
     188         * load ranges and read only information from the config
     189         */
     190
     191        config_option = talloc_asprintf(result, "idmap config %s",
     192                                        result->name);
     193        if (config_option == NULL) {
     194                DEBUG(0, ("Out of memory!\n"));
     195                goto fail;
     196        }
     197
     198        range = lp_parm_const_string(-1, config_option, "range", NULL);
     199        if (range == NULL) {
     200                DEBUG(1, ("idmap range not specified for domain %s\n",
     201                          result->name));
     202                if (check_range) {
     203                        goto fail;
     204                }
     205        } else if (sscanf(range, "%u - %u", &result->low_id,
     206                          &result->high_id) != 2)
     207        {
     208                DEBUG(1, ("invalid range '%s' specified for domain "
     209                          "'%s'\n", range, result->name));
     210                if (check_range) {
     211                        goto fail;
     212                }
     213        }
     214
     215        result->read_only = lp_parm_bool(-1, config_option, "read only", false);
     216
     217        talloc_free(config_option);
     218
     219        if (result->low_id > result->high_id) {
     220                DEBUG(1, ("Error: invalid idmap range detected: %lu - %lu\n",
     221                          (unsigned long)result->low_id,
     222                          (unsigned long)result->high_id));
     223                if (check_range) {
     224                        goto fail;
     225                }
    298226        }
    299227
     
    316244        }
    317245
    318         status = result->methods->init(result, params);
     246        status = result->methods->init(result);
    319247        if (!NT_STATUS_IS_OK(status)) {
    320248                DEBUG(1, ("idmap initialization returned %s\n",
     
    323251        }
    324252
    325         talloc_set_destructor(result, close_domain_destructor);
    326 
    327253        return result;
    328254
    329255fail:
    330         TALLOC_FREE(result);
    331         return NULL;
    332 }
    333 
    334 /**
    335  * Initialize the default domain structure
    336  * @param[in] mem_ctx           memory context for the result
    337  * @result The default domain structure
    338  *
    339  * This routine takes the module name from the "idmap backend" parameter,
    340  * passing a possible parameter like ldap:ldap://ldap-url/ to the module.
    341  */
    342 
    343 static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx)
    344 {
    345         struct idmap_domain *result;
    346         char *modulename;
    347         char *params;
    348 
    349         DEBUG(10, ("idmap_init_default_domain: calling static_init_idmap\n"));
    350 
    351         static_init_idmap;
    352 
    353         if (!parse_idmap_module(talloc_tos(), lp_idmap_backend(), &modulename,
    354                                 &params)) {
    355                 DEBUG(1, ("parse_idmap_module failed\n"));
    356                 return NULL;
    357         }
    358 
    359         DEBUG(3, ("idmap_init: using '%s' as remote backend\n", modulename));
    360 
    361         result = idmap_init_domain(mem_ctx, "*", modulename, params);
    362         if (result == NULL) {
    363                 goto fail;
    364         }
    365 
    366         TALLOC_FREE(modulename);
    367         TALLOC_FREE(params);
    368         return result;
    369 
    370 fail:
    371         TALLOC_FREE(modulename);
    372         TALLOC_FREE(params);
    373256        TALLOC_FREE(result);
    374257        return NULL;
     
    392275        const char *backend;
    393276
     277        idmap_init();
     278
    394279        config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
    395280                                        domname);
     
    405290        }
    406291
    407         result = idmap_init_domain(mem_ctx, domname, backend, NULL);
     292        result = idmap_init_domain(mem_ctx, domname, backend, true);
    408293        if (result == NULL) {
    409294                goto fail;
     
    417302        TALLOC_FREE(result);
    418303        return NULL;
     304}
     305
     306/**
     307 * Initialize the default domain structure
     308 * @param[in] mem_ctx           memory context for the result
     309 * @result The default domain structure
     310 *
     311 * This routine takes the module name from the "idmap backend" parameter,
     312 * passing a possible parameter like ldap:ldap://ldap-url/ to the module.
     313 */
     314
     315static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx)
     316{
     317        return idmap_init_named_domain(mem_ctx, "*");
    419318}
    420319
     
    429328static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx)
    430329{
     330        idmap_init();
     331
    431332        /*
    432333         * Always init the default domain, we can't go without one
     
    444345
    445346        passdb_idmap_domain = idmap_init_domain(NULL, get_global_sam_name(),
    446                                                 "passdb", NULL);
     347                                                "passdb", false);
    447348        if (passdb_idmap_domain == NULL) {
    448349                DEBUG(1, ("Could not init passdb idmap domain\n"));
     
    467368 */
    468369
    469 static struct idmap_domain *idmap_find_domain(const char *domname)
     370struct idmap_domain *idmap_find_domain(const char *domname)
    470371{
    471372        struct idmap_domain *result;
     
    474375        DEBUG(10, ("idmap_find_domain called for domain '%s'\n",
    475376                   domname?domname:"NULL"));
     377
     378        idmap_init();
    476379
    477380        /*
     
    522425void idmap_close(void)
    523426{
    524         if (idmap_alloc_ctx) {
    525                 idmap_alloc_ctx->methods->close_fn();
    526                 idmap_alloc_ctx->methods = NULL;
    527         }
    528         alloc_backends = NULL;
    529427        TALLOC_FREE(default_idmap_domain);
    530428        TALLOC_FREE(passdb_idmap_domain);
     
    533431}
    534432
    535 /**
    536  * Initialize the idmap alloc backend
    537  * @param[out] ctx              Where to put the alloc_ctx?
    538  * @result Did it work fine?
    539  *
    540  * This routine first looks at "idmap alloc backend" and if that is not
    541  * defined, it uses "idmap backend" for the module name.
    542  */
    543 static NTSTATUS idmap_alloc_init(struct idmap_alloc_context **ctx)
    544 {
    545         const char *backend;
    546         char *modulename, *params;
    547         NTSTATUS ret = NT_STATUS_NO_MEMORY;;
    548 
    549         static_init_idmap;
    550 
    551         if (idmap_alloc_ctx != NULL) {
    552                 *ctx = idmap_alloc_ctx;
    553                 return NT_STATUS_OK;
    554         }
    555 
    556         idmap_alloc_ctx = talloc(NULL, struct idmap_alloc_context);
    557         if (idmap_alloc_ctx == NULL) {
    558                 DEBUG(0, ("talloc failed\n"));
    559                 goto fail;
    560         }
    561 
    562         backend = lp_idmap_alloc_backend();
    563         if ((backend == NULL) || (backend[0] == '\0')) {
    564                 backend = lp_idmap_backend();
    565         }
    566 
    567         if (backend == NULL) {
    568                 DEBUG(3, ("no idmap alloc backend defined\n"));
    569                 ret = NT_STATUS_INVALID_PARAMETER;
    570                 goto fail;
    571         }
    572 
    573         if (!parse_idmap_module(idmap_alloc_ctx, backend, &modulename,
    574                                 &params)) {
    575                 DEBUG(1, ("parse_idmap_module %s failed\n", backend));
    576                 goto fail;
    577         }
    578 
    579         idmap_alloc_ctx->methods = get_alloc_methods(modulename);
    580 
    581         if (idmap_alloc_ctx->methods == NULL) {
    582                 ret = smb_probe_module("idmap", modulename);
    583                 if (NT_STATUS_IS_OK(ret)) {
    584                         idmap_alloc_ctx->methods =
    585                                 get_alloc_methods(modulename);
    586                 }
    587         }
    588 
    589         if (idmap_alloc_ctx->methods == NULL) {
    590                 DEBUG(1, ("could not find idmap alloc module %s\n", backend));
    591                 ret = NT_STATUS_INVALID_PARAMETER;
    592                 goto fail;
    593         }
    594 
    595         ret = idmap_alloc_ctx->methods->init(params);
    596 
    597         if (!NT_STATUS_IS_OK(ret)) {
    598                 DEBUG(0, ("ERROR: Initialization failed for alloc "
    599                           "backend, deferred!\n"));
    600                 goto fail;
    601         }
    602 
    603         TALLOC_FREE(modulename);
    604         TALLOC_FREE(params);
    605 
    606         *ctx = idmap_alloc_ctx;
    607         return NT_STATUS_OK;
    608 
    609 fail:
    610         TALLOC_FREE(idmap_alloc_ctx);
    611         return ret;
    612 }
    613 
    614433/**************************************************************************
    615434 idmap allocator interface functions
    616435**************************************************************************/
    617436
     437static NTSTATUS idmap_allocate_unixid(struct unixid *id)
     438{
     439        struct idmap_domain *dom;
     440        NTSTATUS ret;
     441
     442        dom = idmap_find_domain(NULL);
     443
     444        if (dom == NULL) {
     445                return NT_STATUS_UNSUCCESSFUL;
     446        }
     447
     448        if (dom->methods->allocate_id == NULL) {
     449                return NT_STATUS_NOT_IMPLEMENTED;
     450        }
     451
     452        ret = dom->methods->allocate_id(dom, id);
     453
     454        return ret;
     455}
     456
     457
    618458NTSTATUS idmap_allocate_uid(struct unixid *id)
    619459{
    620         struct idmap_alloc_context *ctx;
    621         NTSTATUS ret;
    622 
    623         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
    624                 return ret;
    625         }
    626 
    627460        id->type = ID_TYPE_UID;
    628         return ctx->methods->allocate_id(id);
     461        return idmap_allocate_unixid(id);
    629462}
    630463
    631464NTSTATUS idmap_allocate_gid(struct unixid *id)
    632465{
    633         struct idmap_alloc_context *ctx;
    634         NTSTATUS ret;
    635 
    636         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
    637                 return ret;
    638         }
    639 
    640466        id->type = ID_TYPE_GID;
    641         return ctx->methods->allocate_id(id);
    642 }
    643 
    644 NTSTATUS idmap_set_uid_hwm(struct unixid *id)
    645 {
    646         struct idmap_alloc_context *ctx;
    647         NTSTATUS ret;
    648 
    649         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
    650                 return ret;
    651         }
    652 
    653         id->type = ID_TYPE_UID;
    654         return ctx->methods->set_id_hwm(id);
    655 }
    656 
    657 NTSTATUS idmap_set_gid_hwm(struct unixid *id)
    658 {
    659         struct idmap_alloc_context *ctx;
    660         NTSTATUS ret;
    661 
    662         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
    663                 return ret;
    664         }
    665 
    666         id->type = ID_TYPE_GID;
    667         return ctx->methods->set_id_hwm(id);
    668 }
    669 
    670 NTSTATUS idmap_new_mapping(const struct dom_sid *psid, enum id_type type,
    671                            struct unixid *pxid)
    672 {
    673         struct dom_sid sid;
    674         struct idmap_domain *dom;
    675         struct id_map map;
    676         NTSTATUS status;
    677 
    678         dom = idmap_find_domain(NULL);
    679         if (dom == NULL) {
    680                 DEBUG(3, ("no default domain, no place to write\n"));
    681                 return NT_STATUS_ACCESS_DENIED;
    682         }
    683         if (dom->methods->set_mapping == NULL) {
    684                 DEBUG(3, ("default domain not writable\n"));
    685                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
    686         }
    687 
    688         sid_copy(&sid, psid);
    689         map.sid = &sid;
    690         map.xid.type = type;
    691 
    692         switch (type) {
    693         case ID_TYPE_UID:
    694                 status = idmap_allocate_uid(&map.xid);
    695                 break;
    696         case ID_TYPE_GID:
    697                 status = idmap_allocate_gid(&map.xid);
    698                 break;
    699         default:
    700                 status = NT_STATUS_INVALID_PARAMETER;
    701                 break;
    702         }
    703 
    704         if (!NT_STATUS_IS_OK(status)) {
    705                 DEBUG(3, ("Could not allocate id: %s\n", nt_errstr(status)));
    706                 return status;
    707         }
    708 
    709         map.status = ID_MAPPED;
    710 
    711         DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
    712                    sid_string_dbg(map.sid),
    713                    (map.xid.type == ID_TYPE_UID) ? "UID" : "GID",
    714                    (unsigned long)map.xid.id));
    715 
    716         status = dom->methods->set_mapping(dom, &map);
    717 
    718         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
    719                 struct id_map *ids[2];
    720                 DEBUG(5, ("Mapping for %s exists - retrying to map sid\n",
    721                           sid_string_dbg(map.sid)));
    722                 ids[0] = &map;
    723                 ids[1] = NULL;
    724                 status = dom->methods->sids_to_unixids(dom, ids);
    725         }
    726 
    727         if (!NT_STATUS_IS_OK(status)) {
    728                 DEBUG(3, ("Could not store the new mapping: %s\n",
    729                           nt_errstr(status)));
    730                 return status;
    731         }
    732 
    733         *pxid = map.xid;
    734 
    735         return NT_STATUS_OK;
     467        return idmap_allocate_unixid(id);
    736468}
    737469
     
    772504        struct id_map *maps[2];
    773505
    774          DEBUG(10, ("idmap_backends_sid_to_unixid: domain = '%s', sid = [%s]\n",
    775                     domain?domain:"NULL", sid_string_dbg(id->sid)));
     506        DEBUG(10, ("idmap_backends_sid_to_unixid: domain = '%s', sid = [%s]\n",
     507                   domain?domain:"NULL", sid_string_dbg(id->sid)));
    776508
    777509        maps[0] = id;
     
    779511
    780512        if (sid_check_is_in_builtin(id->sid)
    781             || (sid_check_is_in_our_domain(id->sid))) {
     513            || (sid_check_is_in_our_domain(id->sid)))
     514        {
     515                NTSTATUS status;
     516
     517                DEBUG(10, ("asking passdb...\n"));
    782518
    783519                dom = idmap_init_passdb_domain(NULL);
     
    785521                        return NT_STATUS_NONE_MAPPED;
    786522                }
    787                 return dom->methods->sids_to_unixids(dom, maps);
     523                status = dom->methods->sids_to_unixids(dom, maps);
     524
     525                if (NT_STATUS_IS_OK(status) && id->status == ID_MAPPED) {
     526                        return status;
     527                }
     528
     529                DEBUG(10, ("passdb could not map.\n"));
     530
     531                return NT_STATUS_NONE_MAPPED;
    788532        }
    789533
     
    795539        return dom->methods->sids_to_unixids(dom, maps);
    796540}
    797 
    798 NTSTATUS idmap_set_mapping(const struct id_map *map)
    799 {
    800         struct idmap_domain *dom;
    801 
    802         dom = idmap_find_domain(NULL);
    803         if (dom == NULL) {
    804                 DEBUG(3, ("no default domain, no place to write\n"));
    805                 return NT_STATUS_ACCESS_DENIED;
    806         }
    807         if (dom->methods->set_mapping == NULL) {
    808                 DEBUG(3, ("default domain not writable\n"));
    809                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
    810         }
    811 
    812         return dom->methods->set_mapping(dom, map);
    813 }
    814 
    815 NTSTATUS idmap_remove_mapping(const struct id_map *map)
    816 {
    817         struct idmap_domain *dom;
    818 
    819         dom = idmap_find_domain(NULL);
    820         if (dom == NULL) {
    821                 DEBUG(3, ("no default domain, no place to write\n"));
    822                 return NT_STATUS_ACCESS_DENIED;
    823         }
    824         if (dom->methods->remove_mapping == NULL) {
    825                 DEBUG(3, ("default domain not writable\n"));
    826                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
    827         }
    828 
    829         return dom->methods->remove_mapping(dom, map);
    830 }
Note: See TracChangeset for help on using the changeset viewer.