nsswitch/idmap.c

説明を見る。
00001 /*
00002    Unix SMB/CIFS implementation.
00003    ID Mapping
00004    Copyright (C) Tim Potter 2000
00005    Copyright (C) Jim McDonough <jmcd@us.ibm.com>        2003
00006    Copyright (C) Simo Sorce 2003-2007
00007    Copyright (C) Jeremy Allison 2006
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00022 */
00023 
00024 #include "includes.h"
00025 #include "winbindd.h"
00026 
00027 #undef DBGC_CLASS
00028 #define DBGC_CLASS DBGC_IDMAP
00029 
00030 static_decl_idmap;
00031 
00032 struct idmap_backend {
00033         const char *name;
00034         struct idmap_methods *methods;
00035         struct idmap_backend *prev, *next;
00036 };
00037 
00038 struct idmap_alloc_backend {
00039         const char *name;
00040         struct idmap_alloc_methods *methods;
00041         struct idmap_alloc_backend *prev, *next;
00042 };
00043 
00044 struct idmap_cache_ctx;
00045 
00046 struct idmap_alloc_context {
00047         const char *params;
00048         struct idmap_alloc_methods *methods;
00049         BOOL initialized;
00050 };
00051 
00052 static TALLOC_CTX *idmap_ctx = NULL;
00053 static struct idmap_cache_ctx *idmap_cache;
00054 
00055 static struct idmap_backend *backends = NULL;
00056 static struct idmap_domain **idmap_domains = NULL;
00057 static int num_domains = 0;
00058 static int pdb_dom_num = -1;
00059 static int def_dom_num = -1;
00060 
00061 static struct idmap_alloc_backend *alloc_backends = NULL;
00062 static struct idmap_alloc_context *idmap_alloc_ctx = NULL;
00063 
00064 #define IDMAP_CHECK_RET(ret) do { \
00065         if ( ! NT_STATUS_IS_OK(ret)) { \
00066                 DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); \
00067                         goto done; \
00068         } } while(0)
00069 #define IDMAP_REPORT_RET(ret) do { \
00070         if ( ! NT_STATUS_IS_OK(ret)) { \
00071                 DEBUG(2, ("ERROR: NTSTATUS = 0x%08x\n", NT_STATUS_V(ret))); \
00072         } } while(0)
00073 #define IDMAP_CHECK_ALLOC(mem) do { \
00074         if (!mem) { \
00075                 DEBUG(0, ("Out of memory!\n")); ret = NT_STATUS_NO_MEMORY; \
00076                 goto done; \
00077         } } while(0)
00078 
00079 static struct idmap_methods *get_methods(struct idmap_backend *be,
00080                                          const char *name)
00081 {
00082         struct idmap_backend *b;
00083 
00084         for (b = be; b; b = b->next) {
00085                 if (strequal(b->name, name)) {
00086                         return b->methods;
00087                 }
00088         }
00089 
00090         return NULL;
00091 }
00092 
00093 static struct idmap_alloc_methods *get_alloc_methods(
00094                                                 struct idmap_alloc_backend *be,
00095                                                 const char *name)
00096 {
00097         struct idmap_alloc_backend *b;
00098 
00099         for (b = be; b; b = b->next) {
00100                 if (strequal(b->name, name)) {
00101                         return b->methods;
00102                 }
00103         }
00104 
00105         return NULL;
00106 }
00107 
00108 BOOL idmap_is_offline(void)
00109 {
00110         return ( lp_winbind_offline_logon() &&
00111              get_global_winbindd_state_offline() );
00112 }
00113 
00114 /**********************************************************************
00115  Allow a module to register itself as a method.
00116 **********************************************************************/
00117 
00118 NTSTATUS smb_register_idmap(int version, const char *name,
00119                             struct idmap_methods *methods)
00120 {
00121         struct idmap_methods *test;
00122         struct idmap_backend *entry;
00123 
00124         if (!idmap_ctx) {
00125                 return NT_STATUS_INTERNAL_DB_ERROR;
00126         }
00127 
00128         if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
00129                 DEBUG(0, ("Failed to register idmap module.\n"
00130                           "The module was compiled against "
00131                           "SMB_IDMAP_INTERFACE_VERSION %d,\n"
00132                           "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
00133                           "Please recompile against the current version "
00134                           "of samba!\n",
00135                           version, SMB_IDMAP_INTERFACE_VERSION));
00136                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
00137         }
00138 
00139         if (!name || !name[0] || !methods) {
00140                 DEBUG(0,("Called with NULL pointer or empty name!\n"));
00141                 return NT_STATUS_INVALID_PARAMETER;
00142         }
00143 
00144         test = get_methods(backends, name);
00145         if (test) {
00146                 DEBUG(0,("Idmap module %s already registered!\n", name));
00147                 return NT_STATUS_OBJECT_NAME_COLLISION;
00148         }
00149 
00150         entry = talloc(idmap_ctx, struct idmap_backend);
00151         if ( ! entry) {
00152                 DEBUG(0,("Out of memory!\n"));
00153                 return NT_STATUS_NO_MEMORY;
00154         }
00155         entry->name = talloc_strdup(idmap_ctx, name);
00156         if ( ! entry->name) {
00157                 DEBUG(0,("Out of memory!\n"));
00158                 return NT_STATUS_NO_MEMORY;
00159         }
00160         entry->methods = methods;
00161 
00162         DLIST_ADD(backends, entry);
00163         DEBUG(5, ("Successfully added idmap backend '%s'\n", name));
00164         return NT_STATUS_OK;
00165 }
00166 
00167 /**********************************************************************
00168  Allow a module to register itself as a method.
00169 **********************************************************************/
00170 
00171 NTSTATUS smb_register_idmap_alloc(int version, const char *name,
00172                                   struct idmap_alloc_methods *methods)
00173 {
00174         struct idmap_alloc_methods *test;
00175         struct idmap_alloc_backend *entry;
00176 
00177         if (!idmap_ctx) {
00178                 return NT_STATUS_INTERNAL_DB_ERROR;
00179         }
00180 
00181         if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
00182                 DEBUG(0, ("Failed to register idmap alloc module.\n"
00183                           "The module was compiled against "
00184                           "SMB_IDMAP_INTERFACE_VERSION %d,\n"
00185                           "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
00186                           "Please recompile against the current version "
00187                           "of samba!\n",
00188                           version, SMB_IDMAP_INTERFACE_VERSION));
00189                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
00190         }
00191 
00192         if (!name || !name[0] || !methods) {
00193                 DEBUG(0,("Called with NULL pointer or empty name!\n"));
00194                 return NT_STATUS_INVALID_PARAMETER;
00195         }
00196 
00197         test = get_alloc_methods(alloc_backends, name);
00198         if (test) {
00199                 DEBUG(0,("idmap_alloc module %s already registered!\n", name));
00200                 return NT_STATUS_OBJECT_NAME_COLLISION;
00201         }
00202 
00203         entry = talloc(idmap_ctx, struct idmap_alloc_backend);
00204         if ( ! entry) {
00205                 DEBUG(0,("Out of memory!\n"));
00206                 return NT_STATUS_NO_MEMORY;
00207         }
00208         entry->name = talloc_strdup(idmap_ctx, name);
00209         if ( ! entry->name) {
00210                 DEBUG(0,("Out of memory!\n"));
00211                 return NT_STATUS_NO_MEMORY;
00212         }
00213         entry->methods = methods;
00214 
00215         DLIST_ADD(alloc_backends, entry);
00216         DEBUG(5, ("Successfully added idmap alloc backend '%s'\n", name));
00217         return NT_STATUS_OK;
00218 }
00219 
00220 static int close_domain_destructor(struct idmap_domain *dom)
00221 {
00222         NTSTATUS ret;
00223 
00224         ret = dom->methods->close_fn(dom);
00225         if (!NT_STATUS_IS_OK(ret)) {
00226                 DEBUG(3, ("Failed to close idmap domain [%s]!\n", dom->name));
00227         }
00228 
00229         return 0;
00230 }
00231 
00232 /**************************************************************************
00233  Shutdown.
00234 **************************************************************************/
00235 
00236 NTSTATUS idmap_close(void)
00237 {
00238         /* close the alloc backend first before freeing idmap_ctx */
00239         if (idmap_alloc_ctx) {
00240                 idmap_alloc_ctx->methods->close_fn();
00241                 idmap_alloc_ctx->methods = NULL;
00242         }
00243         alloc_backends = NULL;
00244 
00245         /* this talloc_free call will fire the talloc destructors
00246          * that will free all active backends resources */
00247         TALLOC_FREE(idmap_ctx);
00248         idmap_cache = NULL;
00249         idmap_domains = NULL;
00250         backends = NULL;
00251 
00252         return NT_STATUS_OK;
00253 }
00254 
00255 /****************************************************************************
00256  ****************************************************************************/
00257 
00258 NTSTATUS idmap_init_cache(void)
00259 {
00260         /* Always initialize the cache.  We'll have to delay initialization
00261            of backends if we are offline */
00262 
00263         if ( idmap_ctx ) {
00264                 return NT_STATUS_OK;
00265         }
00266 
00267         if ( (idmap_ctx = talloc_named_const(NULL, 0, "idmap_ctx")) == NULL ) {
00268                 return NT_STATUS_NO_MEMORY;
00269         }
00270 
00271         if ( (idmap_cache = idmap_cache_init(idmap_ctx)) == NULL ) {
00272                 return NT_STATUS_UNSUCCESSFUL;
00273         }
00274 
00275         return NT_STATUS_OK;
00276 }
00277 
00278 /****************************************************************************
00279  ****************************************************************************/
00280 
00281 NTSTATUS idmap_init(void)
00282 {
00283         NTSTATUS ret;
00284         static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL;
00285         struct idmap_domain *dom;
00286         char *compat_backend = NULL;
00287         char *compat_params = NULL;
00288         const char **dom_list = NULL;
00289         const char *default_domain = NULL;
00290         char *alloc_backend = NULL;
00291         BOOL default_already_defined = False;
00292         BOOL pri_dom_is_in_list = False;
00293         int compat = 0;
00294         int i;
00295 
00296         ret = idmap_init_cache();
00297         if (!NT_STATUS_IS_OK(ret))
00298                 return ret;
00299 
00300         if (NT_STATUS_IS_OK(idmap_init_status))
00301                 return NT_STATUS_OK;
00302 
00303         static_init_idmap;
00304 
00305         dom_list = lp_idmap_domains();
00306 
00307         if ( lp_idmap_backend() ) {
00308                 const char **compat_list = lp_idmap_backend();
00309                 char *p = NULL;
00310                 const char *q = NULL;
00311 
00312                 if (dom_list) {
00313                         DEBUG(0, ("WARNING: idmap backend and idmap domains "
00314                                   "are mutually excusive!\n"));
00315                         DEBUGADD(0,("idmap backend option will be IGNORED!\n"));
00316                 } else {
00317                         compat = 1;
00318 
00319                         /* strip any leading idmap_ prefix of */
00320                         if (strncmp(*compat_list, "idmap_", 6) == 0 ) {
00321                                 q = *compat_list += 6;
00322                                 DEBUG(0, ("WARNING: idmap backend uses obsolete"
00323                                           " and deprecated 'idmap_' prefix.\n"
00324                                           "Please replace 'idmap_%s' by '%s' in"
00325                                           " %s\n", q, q, dyn_CONFIGFILE));
00326                                 compat_backend = talloc_strdup(idmap_ctx, q);
00327                         } else {
00328                                 compat_backend = talloc_strdup(idmap_ctx,
00329                                                                 *compat_list);
00330                         }
00331 
00332                         if (compat_backend == NULL) {
00333                                 ret = NT_STATUS_NO_MEMORY;
00334                                 goto done;
00335                         }
00336 
00337                         /* separate the backend and module arguements */
00338                         if ((p = strchr(compat_backend, ':')) != NULL) {
00339                                 *p = '\0';
00340                                 compat_params = p + 1;
00341                         }
00342                 }
00343         } else if ( !dom_list ) {
00344                 /* Back compatible: without idmap domains and explicit
00345                    idmap backend.  Taking default idmap backend: tdb */
00346 
00347                 compat = 1;
00348                 compat_backend = talloc_strdup( idmap_ctx, "tdb");
00349                 compat_params = compat_backend;
00350         }
00351 
00352         if ( ! dom_list) {
00353                 /* generate a list with our main domain */
00354                 char ** dl;
00355 
00356                 dl = talloc_array(idmap_ctx, char *, 2);
00357                 if (dl == NULL) {
00358                         ret = NT_STATUS_NO_MEMORY;
00359                         goto done;
00360                 }
00361                 dl[0] = talloc_strdup(dl, lp_workgroup());
00362                 if (dl[0] == NULL) {
00363                         ret = NT_STATUS_NO_MEMORY;
00364                         goto done;
00365                 }
00366 
00367                 /* terminate */
00368                 dl[1] = NULL;
00369 
00370                 dom_list = (const char **)dl;
00371                 default_domain = dl[0];
00372         }
00373 
00374         /***************************
00375          * initialize idmap domains
00376          */
00377         DEBUG(1, ("Initializing idmap domains\n"));
00378 
00379         for (i=0, num_domains=0; dom_list[i]; i++) {
00380                 const char *parm_backend;
00381                 char *config_option;
00382 
00383                 /* ignore BUILTIN and local MACHINE domains */
00384                 if (strequal(dom_list[i], "BUILTIN")
00385                      || strequal(dom_list[i], get_global_sam_name()))
00386                 {
00387                         DEBUG(0,("idmap_init: Ignoring domain %s\n",
00388                                  dom_list[i]));
00389                         continue;
00390                 }
00391 
00392                 if ((dom_list[i] != default_domain) &&
00393                     strequal(dom_list[i], lp_workgroup())) {
00394                         pri_dom_is_in_list = True;
00395                 }
00396                 /* init domain */
00397 
00398                 dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain);
00399                 IDMAP_CHECK_ALLOC(dom);
00400 
00401                 dom->name = talloc_strdup(dom, dom_list[i]);
00402                 IDMAP_CHECK_ALLOC(dom->name);
00403 
00404                 config_option = talloc_asprintf(dom, "idmap config %s",
00405                                                 dom->name);
00406                 IDMAP_CHECK_ALLOC(config_option);
00407 
00408                 /* default or specific ? */
00409 
00410                 dom->default_domain = lp_parm_bool(-1, config_option,
00411                                                    "default", False);
00412 
00413                 if (dom->default_domain ||
00414                     (default_domain && strequal(dom_list[i], default_domain))) {
00415 
00416                         /* make sure this is set even when we match
00417                          * default_domain */
00418                         dom->default_domain = True;
00419 
00420                         if (default_already_defined) {
00421                                 DEBUG(1, ("ERROR: Multiple domains defined as"
00422                                           " default!\n"));
00423                                 ret = NT_STATUS_INVALID_PARAMETER;
00424                                 goto done;
00425                         }
00426 
00427                         default_already_defined = True;
00428 
00429                 }
00430 
00431                 dom->readonly = lp_parm_bool(-1, config_option,
00432                                              "readonly", False);
00433 
00434                 /* find associated backend (default: tdb) */
00435                 if (compat) {
00436                         parm_backend = talloc_strdup(idmap_ctx, compat_backend);
00437                 } else {
00438                         parm_backend = talloc_strdup(idmap_ctx,
00439                                                      lp_parm_const_string(
00440                                                         -1, config_option,
00441                                                         "backend", "tdb"));
00442                 }
00443                 IDMAP_CHECK_ALLOC(parm_backend);
00444 
00445                 /* get the backend methods for this domain */
00446                 dom->methods = get_methods(backends, parm_backend);
00447 
00448                 if ( ! dom->methods) {
00449                         ret = smb_probe_module("idmap", parm_backend);
00450                         if (NT_STATUS_IS_OK(ret)) {
00451                                 dom->methods = get_methods(backends,
00452                                                            parm_backend);
00453                         }
00454                 }
00455                 if ( ! dom->methods) {
00456                         DEBUG(0, ("ERROR: Could not get methods for "
00457                                   "backend %s\n", parm_backend));
00458                         ret = NT_STATUS_UNSUCCESSFUL;
00459                         goto done;
00460                 }
00461 
00462                 /* check the set_mapping function exists otherwise mark the
00463                  * module as readonly */
00464                 if ( ! dom->methods->set_mapping) {
00465                         DEBUG(5, ("Forcing to readonly, as this module can't"
00466                                   " store arbitrary mappings.\n"));
00467                         dom->readonly = True;
00468                 }
00469 
00470                 /* now that we have methods,
00471                  * set the destructor for this domain */
00472                 talloc_set_destructor(dom, close_domain_destructor);
00473 
00474                 if (compat_params) {
00475                         dom->params = talloc_strdup(dom, compat_params);
00476                         IDMAP_CHECK_ALLOC(dom->params);
00477                 } else {
00478                         dom->params = NULL;
00479                 }
00480 
00481                 /* Finally instance a backend copy for this domain */
00482                 ret = dom->methods->init(dom);
00483                 if ( ! NT_STATUS_IS_OK(ret)) {
00484                         DEBUG(0, ("ERROR: Initialization failed for backend "
00485                                   "%s (domain %s), deferred!\n",
00486                                   parm_backend, dom->name));
00487                 }
00488                 idmap_domains = talloc_realloc(idmap_ctx, idmap_domains,
00489                                                 struct idmap_domain *, i+1);
00490                 if ( ! idmap_domains) {
00491                         DEBUG(0, ("Out of memory!\n"));
00492                         ret = NT_STATUS_NO_MEMORY;
00493                         goto done;
00494                 }
00495                 idmap_domains[num_domains] = dom;
00496 
00497                 /* save default domain position for future uses */
00498                 if (dom->default_domain) {
00499                         def_dom_num = num_domains;
00500                 }
00501 
00502                 /* Bump counter to next available slot */
00503 
00504                 num_domains++;
00505 
00506                 DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n",
00507                                 dom->name, parm_backend,
00508                                 dom->default_domain?"":"not ",
00509                                 dom->readonly?"":"not "));
00510 
00511                 talloc_free(config_option);
00512         }
00513 
00514         /* on DCs we need to add idmap_tdb as the default backend if compat is
00515          * defined (when the old implicit configuration is used)
00516          * This is not done in the previous loop a on member server we exclude
00517          * the local domain. But on a DC the local domain is the only domain
00518          * available therefore we are left with no default domain */
00519         if (((lp_server_role() == ROLE_DOMAIN_PDC) ||
00520              (lp_server_role() == ROLE_DOMAIN_BDC)) &&
00521             ((num_domains == 0) && (compat == 1))) {
00522 
00523                 dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain);
00524                 IDMAP_CHECK_ALLOC(dom);
00525 
00526                 dom->name = talloc_strdup(dom, "__default__");
00527                 IDMAP_CHECK_ALLOC(dom->name);
00528 
00529                 dom->default_domain = True;
00530                 dom->readonly = False;
00531 
00532                 /* get the backend methods for this domain */
00533                 dom->methods = get_methods(backends, compat_backend);
00534 
00535                 if ( ! dom->methods) {
00536                         ret = smb_probe_module("idmap", compat_backend);
00537                         if (NT_STATUS_IS_OK(ret)) {
00538                                 dom->methods = get_methods(backends,
00539                                                            compat_backend);
00540                         }
00541                 }
00542                 if ( ! dom->methods) {
00543                         DEBUG(0, ("ERROR: Could not get methods for "
00544                                   "backend %s\n", compat_backend));
00545                         ret = NT_STATUS_UNSUCCESSFUL;
00546                         goto done;
00547                 }
00548 
00549                 /* now that we have methods,
00550                  * set the destructor for this domain */
00551                 talloc_set_destructor(dom, close_domain_destructor);
00552 
00553                 dom->params = talloc_strdup(dom, compat_params);
00554                 IDMAP_CHECK_ALLOC(dom->params);
00555 
00556                 /* Finally instance a backend copy for this domain */
00557                 ret = dom->methods->init(dom);
00558                 if ( ! NT_STATUS_IS_OK(ret)) {
00559                         DEBUG(0, ("ERROR: Initialization failed for backend "
00560                                   "%s (domain %s), deferred!\n",
00561                                   compat_backend, dom->name));
00562                 }
00563                 idmap_domains = talloc_realloc(idmap_ctx, idmap_domains,
00564                                                 struct idmap_domain *, 2);
00565                 if ( ! idmap_domains) {
00566                         DEBUG(0, ("Out of memory!\n"));
00567                         ret = NT_STATUS_NO_MEMORY;
00568                         goto done;
00569                 }
00570                 idmap_domains[num_domains] = dom;
00571 
00572                 def_dom_num = num_domains;
00573 
00574                 /* Bump counter to next available slot */
00575 
00576                 num_domains++;
00577 
00578                 DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n",
00579                                 dom->name, compat_backend,
00580                                 dom->default_domain?"":"not ",
00581                                 dom->readonly?"":"not "));
00582         }
00583 
00584         /* automatically add idmap_nss backend if needed */
00585         if ((lp_server_role() == ROLE_DOMAIN_MEMBER) &&
00586             ( ! pri_dom_is_in_list) &&
00587             lp_winbind_trusted_domains_only()) {
00588 
00589                 dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain);
00590                 IDMAP_CHECK_ALLOC(dom);
00591 
00592                 dom->name = talloc_strdup(dom, lp_workgroup());
00593                 IDMAP_CHECK_ALLOC(dom->name);
00594 
00595                 dom->default_domain = False;
00596                 dom->readonly = True;
00597 
00598                 /* get the backend methods for passdb */
00599                 dom->methods = get_methods(backends, "nss");
00600 
00601                 /* (the nss module is always statically linked) */
00602                 if ( ! dom->methods) {
00603                         DEBUG(0, ("ERROR: No methods for idmap_nss ?!\n"));
00604                         ret = NT_STATUS_UNSUCCESSFUL;
00605                         goto done;
00606                 }
00607 
00608                 /* now that we have methods,
00609                  * set the destructor for this domain */
00610                 talloc_set_destructor(dom, close_domain_destructor);
00611 
00612                 if (compat_params) {
00613                         dom->params = talloc_strdup(dom, compat_params);
00614                         IDMAP_CHECK_ALLOC(dom->params);
00615                 } else {
00616                         dom->params = NULL;
00617                 }
00618 
00619                 /* Finally instance a backend copy for this domain */
00620                 ret = dom->methods->init(dom);
00621                 if ( ! NT_STATUS_IS_OK(ret)) {
00622                         DEBUG(0, ("ERROR: Init. failed for idmap_nss ?!\n"));
00623                         ret = NT_STATUS_UNSUCCESSFUL;
00624                         goto done;
00625                 }
00626 
00627                 idmap_domains = talloc_realloc(idmap_ctx,
00628                                                 idmap_domains,
00629                                                 struct idmap_domain *,
00630                                                 num_domains+1);
00631                 if ( ! idmap_domains) {
00632                         DEBUG(0, ("Out of memory!\n"));
00633                         ret = NT_STATUS_NO_MEMORY;
00634                         goto done;
00635                 }
00636                 idmap_domains[num_domains] = dom;
00637 
00638                 DEBUG(10, ("Domain %s - Backend nss - not default - readonly\n",
00639                            dom->name ));
00640 
00641                 num_domains++;
00642         }
00643 
00644         /**** automatically add idmap_passdb backend ****/
00645         dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain);
00646         IDMAP_CHECK_ALLOC(dom);
00647 
00648         dom->name = talloc_strdup(dom, get_global_sam_name());
00649         IDMAP_CHECK_ALLOC(dom->name);
00650 
00651         dom->default_domain = False;
00652         dom->readonly = True;
00653 
00654         /* get the backend methods for passdb */
00655         dom->methods = get_methods(backends, "passdb");
00656 
00657         /* (the passdb module is always statically linked) */
00658         if ( ! dom->methods) {
00659                 DEBUG(0, ("ERROR: No methods for idmap_passdb ?!\n"));
00660                 ret = NT_STATUS_UNSUCCESSFUL;
00661                 goto done;
00662         }
00663 
00664         /* now that we have methods, set the destructor for this domain */
00665         talloc_set_destructor(dom, close_domain_destructor);
00666 
00667         if (compat_params) {
00668                 dom->params = talloc_strdup(dom, compat_params);
00669                 IDMAP_CHECK_ALLOC(dom->params);
00670         } else {
00671                 dom->params = NULL;
00672         }
00673 
00674         /* Finally instance a backend copy for this domain */
00675         ret = dom->methods->init(dom);
00676         if ( ! NT_STATUS_IS_OK(ret)) {
00677                 DEBUG(0, ("ERROR: Init. failed for idmap_passdb ?!\n"));
00678                 ret = NT_STATUS_UNSUCCESSFUL;
00679                 goto done;
00680         }
00681 
00682         idmap_domains = talloc_realloc(idmap_ctx,
00683                                         idmap_domains,
00684                                         struct idmap_domain *,
00685                                         num_domains+1);
00686         if ( ! idmap_domains) {
00687                 DEBUG(0, ("Out of memory!\n"));
00688                 ret = NT_STATUS_NO_MEMORY;
00689                 goto done;
00690         }
00691         idmap_domains[num_domains] = dom;
00692 
00693         /* needed to handle special BUILTIN and wellknown SIDs cases */
00694         pdb_dom_num = num_domains;
00695 
00696         DEBUG(10, ("Domain %s - Backend passdb - not default - readonly\n",
00697                    dom->name));
00698 
00699         num_domains++;
00700         /**** finished adding idmap_passdb backend ****/
00701 
00702         /* sort domains so that the default is the last one */
00703         /* don't sort if no default domain defined */
00704         if (def_dom_num != -1 && def_dom_num != num_domains-1) {
00705                 /* default is not last, move it */
00706                 struct idmap_domain *tmp;
00707 
00708                 if (pdb_dom_num > def_dom_num) {
00709                         pdb_dom_num --;
00710 
00711                 } else if (pdb_dom_num == def_dom_num) { /* ?? */
00712                         pdb_dom_num = num_domains - 1;
00713                 }
00714 
00715                 tmp = idmap_domains[def_dom_num];
00716 
00717                 for (i = def_dom_num; i < num_domains-1; i++) {
00718                         idmap_domains[i] = idmap_domains[i+1];
00719                 }
00720                 idmap_domains[i] = tmp;
00721                 def_dom_num = i;
00722         }
00723 
00724 
00725         /* Initialize alloc module */
00726 
00727         DEBUG(3, ("Initializing idmap alloc module\n"));
00728 
00729         alloc_backend = NULL;
00730         if (compat) {
00731                 alloc_backend = talloc_strdup(idmap_ctx, compat_backend);
00732         } else {
00733                 char *ab = lp_idmap_alloc_backend();
00734 
00735                 if (ab && (ab[0] != '\0')) {
00736                         alloc_backend = talloc_strdup(idmap_ctx,
00737                                                       lp_idmap_alloc_backend());
00738                 }
00739         }
00740 
00741         if ( alloc_backend ) {
00742 
00743                 idmap_alloc_ctx = TALLOC_ZERO_P(idmap_ctx,
00744                                                 struct idmap_alloc_context);
00745                 IDMAP_CHECK_ALLOC(idmap_alloc_ctx);
00746 
00747                 idmap_alloc_ctx->methods = get_alloc_methods(alloc_backends,
00748                                                              alloc_backend);
00749                 if ( ! idmap_alloc_ctx->methods) {
00750                         ret = smb_probe_module("idmap", alloc_backend);
00751                         if (NT_STATUS_IS_OK(ret)) {
00752                                 idmap_alloc_ctx->methods =
00753                                         get_alloc_methods(alloc_backends,
00754                                                           alloc_backend);
00755                         }
00756                 }
00757                 if (idmap_alloc_ctx->methods) {
00758 
00759                         if (compat_params) {
00760                                 idmap_alloc_ctx->params =
00761                                         talloc_strdup(idmap_alloc_ctx,
00762                                                       compat_params);
00763                                 IDMAP_CHECK_ALLOC(idmap_alloc_ctx->params);
00764                         } else {
00765                                 idmap_alloc_ctx->params = NULL;
00766                         }
00767 
00768                         ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params);
00769                         if ( ! NT_STATUS_IS_OK(ret)) {
00770                                 DEBUG(0, ("ERROR: Initialization failed for "
00771                                           "alloc backend %s, deferred!\n",
00772                                           alloc_backend));
00773                         } else {
00774                                 idmap_alloc_ctx->initialized = True;
00775                         }
00776                 } else {
00777                         DEBUG(2, ("idmap_init: Unable to get methods for "
00778                                   "alloc backend %s\n",
00779                                   alloc_backend));
00780                         /* certain compat backends are just readonly */
00781                         if ( compat ) {
00782                                 TALLOC_FREE(idmap_alloc_ctx);
00783                                 ret = NT_STATUS_OK;
00784                         } else {
00785                                 ret = NT_STATUS_UNSUCCESSFUL;
00786                         }
00787                 }
00788         }
00789 
00790         /* cleanpu temporary strings */
00791         TALLOC_FREE( compat_backend );
00792 
00793         idmap_init_status = NT_STATUS_OK;
00794 
00795         return ret;
00796 
00797 done:
00798         DEBUG(0, ("Aborting IDMAP Initialization ...\n"));
00799         idmap_close();
00800 
00801         return ret;
00802 }
00803 
00804 static NTSTATUS idmap_alloc_init(void)
00805 {
00806         NTSTATUS ret;
00807 
00808         if (! NT_STATUS_IS_OK(ret = idmap_init())) {
00809                 return ret;
00810         }
00811 
00812         if ( ! idmap_alloc_ctx) {
00813                 return NT_STATUS_NOT_SUPPORTED;
00814         }
00815 
00816         if ( ! idmap_alloc_ctx->initialized) {
00817                 ret = idmap_alloc_ctx->methods->init(idmap_alloc_ctx->params);
00818                 if ( ! NT_STATUS_IS_OK(ret)) {
00819                         DEBUG(0, ("ERROR: Initialization failed for alloc "
00820                                   "backend, deferred!\n"));
00821                         return ret;
00822                 } else {
00823                         idmap_alloc_ctx->initialized = True;
00824                 }
00825         }
00826 
00827         return NT_STATUS_OK;
00828 }
00829 
00830 /**************************************************************************
00831  idmap allocator interface functions
00832 **************************************************************************/
00833 
00834 NTSTATUS idmap_allocate_uid(struct unixid *id)
00835 {
00836         NTSTATUS ret;
00837 
00838         if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
00839                 return ret;
00840         }
00841 
00842         id->type = ID_TYPE_UID;
00843         return idmap_alloc_ctx->methods->allocate_id(id);
00844 }
00845 
00846 NTSTATUS idmap_allocate_gid(struct unixid *id)
00847 {
00848         NTSTATUS ret;
00849 
00850         if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
00851                 return ret;
00852         }
00853 
00854         id->type = ID_TYPE_GID;
00855         return idmap_alloc_ctx->methods->allocate_id(id);
00856 }
00857 
00858 NTSTATUS idmap_set_uid_hwm(struct unixid *id)
00859 {
00860         NTSTATUS ret;
00861 
00862         if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
00863                 return ret;
00864         }
00865 
00866         id->type = ID_TYPE_UID;
00867         return idmap_alloc_ctx->methods->set_id_hwm(id);
00868 }
00869 
00870 NTSTATUS idmap_set_gid_hwm(struct unixid *id)
00871 {
00872         NTSTATUS ret;
00873 
00874         if (! NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
00875                 return ret;
00876         }
00877 
00878         id->type = ID_TYPE_GID;
00879         return idmap_alloc_ctx->methods->set_id_hwm(id);
00880 }
00881 
00882 /******************************************************************************
00883  Lookup an idmap_domain give a full user or group SID
00884  ******************************************************************************/
00885 
00886 static struct idmap_domain* find_idmap_domain_from_sid( DOM_SID *account_sid )
00887 {
00888         DOM_SID domain_sid;
00889         uint32 rid;
00890         struct winbindd_domain *domain = NULL;
00891         int i;
00892 
00893         /* 1. Handle BUILTIN or Special SIDs and prevent them from
00894            falling into the default domain space (if we have a
00895            configured passdb backend. */
00896 
00897         if ( (pdb_dom_num != -1) &&
00898              (sid_check_is_in_builtin(account_sid) ||
00899               sid_check_is_in_wellknown_domain(account_sid) ||
00900               sid_check_is_in_unix_groups(account_sid) ||
00901               sid_check_is_in_unix_users(account_sid)) )
00902         {
00903                 return idmap_domains[pdb_dom_num];
00904         }
00905 
00906         /* 2. Lookup the winbindd_domain from the account_sid */
00907 
00908         sid_copy( &domain_sid, account_sid );
00909         sid_split_rid( &domain_sid, &rid );
00910         domain = find_domain_from_sid_noinit( &domain_sid );
00911 
00912         for (i = 0; domain && i < num_domains; i++) {
00913                 if ( strequal( idmap_domains[i]->name, domain->name ) ) {
00914                         return idmap_domains[i];
00915                 }
00916         }
00917 
00918         /* 3. Fall back to the default domain */
00919 
00920         if ( def_dom_num != -1 ) {
00921                 return idmap_domains[def_dom_num];
00922         }
00923 
00924         return NULL;
00925 }
00926 
00927 /******************************************************************************
00928  Lookup an index given an idmap_domain pointer
00929  ******************************************************************************/
00930 
00931 static uint32 find_idmap_domain_index( struct idmap_domain *id_domain)
00932 {
00933         int i;
00934 
00935         for (i = 0; i < num_domains; i++) {
00936                 if ( idmap_domains[i] == id_domain )
00937                         return i;
00938         }
00939 
00940         return -1;
00941 }
00942 
00943 
00944 /*********************************************************
00945  Check if creating a mapping is permitted for the domain
00946 *********************************************************/
00947 
00948 static NTSTATUS idmap_can_map(const struct id_map *map,
00949                               struct idmap_domain **ret_dom)
00950 {
00951         struct idmap_domain *dom;
00952 
00953         /* Check we do not create mappings for our own local domain,
00954          * or BUILTIN or special SIDs */
00955         if ((sid_compare_domain(map->sid, get_global_sam_sid()) == 0) ||
00956             sid_check_is_in_builtin(map->sid) ||
00957             sid_check_is_in_wellknown_domain(map->sid)) {
00958                 DEBUG(10, ("We are not supposed to create mappings for "
00959                            "our own domains (local, builtin, specials)\n"));
00960                 return NT_STATUS_UNSUCCESSFUL;
00961         }
00962 
00963         /* Special check for trusted domain only = Yes */
00964         if (lp_winbind_trusted_domains_only()) {
00965                 struct winbindd_domain *wdom = find_our_domain();
00966                 if (wdom && (sid_compare_domain(map->sid, &wdom->sid) == 0)) {
00967                         DEBUG(10, ("We are not supposed to create mappings for "
00968                                    "our primary domain when <trusted domain "
00969                                    "only> is True\n"));
00970                         DEBUGADD(10, ("Leave [%s] unmapped\n",
00971                                       sid_string_static(map->sid)));
00972                         return NT_STATUS_UNSUCCESSFUL;
00973                 }
00974         }
00975 
00976         if ( (dom = find_idmap_domain_from_sid( map->sid )) == NULL ) {
00977                 /* huh, couldn't find a suitable domain,
00978                  *  let's just leave it unmapped */
00979                 DEBUG(10, ("Could not find idmap backend for SID %s\n",
00980                            sid_string_static(map->sid)));
00981                 return NT_STATUS_NO_SUCH_DOMAIN;
00982         }
00983 
00984         if (dom->readonly) {
00985                 /* ouch the domain is read only,
00986                  *  let's just leave it unmapped */
00987                 DEBUG(10, ("idmap backend for SID %s is READONLY!\n",
00988                            sid_string_static(map->sid)));
00989                 return NT_STATUS_UNSUCCESSFUL;
00990         }
00991 
00992         *ret_dom = dom;
00993         return NT_STATUS_OK;
00994 }
00995 
00996 static NTSTATUS idmap_new_mapping(TALLOC_CTX *ctx, struct id_map *map)
00997 {
00998         NTSTATUS ret;
00999         struct idmap_domain *dom;
01000 
01001         /* If we are offline we cannot lookup SIDs, deny mapping */
01002         if (idmap_is_offline()) {
01003                 return NT_STATUS_FILE_IS_OFFLINE;
01004         }
01005 
01006         ret = idmap_can_map(map, &dom);
01007         if ( ! NT_STATUS_IS_OK(ret)) {
01008                 return NT_STATUS_NONE_MAPPED;
01009         }
01010 
01011         /* check if this is a valid SID and then map it */
01012         switch (map->xid.type) {
01013         case ID_TYPE_UID:
01014                 ret = idmap_allocate_uid(&map->xid);
01015                 if ( ! NT_STATUS_IS_OK(ret)) {
01016                         /* can't allocate id, let's just leave it unmapped */
01017                         DEBUG(2, ("uid allocation failed! "
01018                                   "Can't create mapping\n"));
01019                         return NT_STATUS_NONE_MAPPED;
01020                 }
01021                 break;
01022         case ID_TYPE_GID:
01023                 ret = idmap_allocate_gid(&map->xid);
01024                 if ( ! NT_STATUS_IS_OK(ret)) {
01025                         /* can't allocate id, let's just leave it unmapped */
01026                         DEBUG(2, ("gid allocation failed! "
01027                                   "Can't create mapping\n"));
01028                         return NT_STATUS_NONE_MAPPED;
01029                 }
01030                 break;
01031         default:
01032                 /* invalid sid, let's just leave it unmapped */
01033                 DEBUG(3,("idmap_new_mapping: Refusing to create a "
01034                          "mapping for an unspecified ID type.\n"));
01035                 return NT_STATUS_NONE_MAPPED;
01036         }
01037 
01038         /* ok, got a new id, let's set a mapping */
01039         map->status = ID_MAPPED;
01040 
01041         DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
01042                    sid_string_static(map->sid),
01043                    (map->xid.type == ID_TYPE_UID) ? "UID" : "GID",
01044                    (unsigned long)map->xid.id));
01045         ret = dom->methods->set_mapping(dom, map);
01046 
01047         if ( ! NT_STATUS_IS_OK(ret)) {
01048                 /* something wrong here :-( */
01049                 DEBUG(2, ("Failed to commit mapping\n!"));
01050 
01051         /* TODO: would it make sense to have an "unalloc_id function?" */
01052 
01053                 return NT_STATUS_NONE_MAPPED;
01054         }
01055 
01056         return NT_STATUS_OK;
01057 }
01058 
01059 static NTSTATUS idmap_backends_set_mapping(const struct id_map *map)
01060 {
01061         struct idmap_domain *dom;
01062         NTSTATUS ret;
01063 
01064         DEBUG(10, ("Setting mapping %s <-> %s %lu\n",
01065                    sid_string_static(map->sid),
01066                    (map->xid.type == ID_TYPE_UID) ? "UID" : "GID",
01067                    (unsigned long)map->xid.id));
01068 
01069         ret = idmap_can_map(map, &dom);
01070         if ( ! NT_STATUS_IS_OK(ret)) {
01071                 return ret;
01072         }
01073 
01074         DEBUG(10,("set_mapping for domain %s\n", dom->name ));
01075 
01076         return dom->methods->set_mapping(dom, map);
01077 }
01078 
01079 static NTSTATUS idmap_backends_unixids_to_sids(struct id_map **ids)
01080 {
01081         struct idmap_domain *dom;
01082         struct id_map **unmapped;
01083         struct id_map **_ids;
01084         TALLOC_CTX *ctx;
01085         NTSTATUS ret;
01086         int i, u, n;
01087 
01088         if (!ids || !*ids) {
01089                 DEBUG(1, ("Invalid list of maps\n"));
01090                 return NT_STATUS_INVALID_PARAMETER;
01091         }
01092 
01093         ctx = talloc_named_const(NULL, 0, "idmap_backends_unixids_to_sids ctx");
01094         if ( ! ctx) {
01095                 DEBUG(0, ("Out of memory!\n"));
01096                 return NT_STATUS_NO_MEMORY;
01097         }
01098 
01099         DEBUG(10, ("Query backends to map ids->sids\n"));
01100 
01101         /* start from the default (the last one) and then if there are still
01102          * unmapped entries cycle through the others */
01103 
01104         _ids = ids;
01105 
01106         unmapped = NULL;
01107         for (n = num_domains-1; n >= 0; n--) { /* cycle backwards */
01108 
01109                 dom = idmap_domains[n];
01110 
01111                 DEBUG(10, ("Query sids from domain %s\n", dom->name));
01112 
01113                 ret = dom->methods->unixids_to_sids(dom, _ids);
01114                 IDMAP_REPORT_RET(ret);
01115 
01116                 unmapped = NULL;
01117 
01118                 for (i = 0, u = 0; _ids[i]; i++) {
01119                         if (_ids[i]->status != ID_MAPPED) {
01120                                 unmapped = talloc_realloc(ctx, unmapped,
01121                                                         struct id_map *, u + 2);
01122                                 IDMAP_CHECK_ALLOC(unmapped);
01123                                 unmapped[u] = _ids[i];
01124                                 u++;
01125                         }
01126                 }
01127                 if (unmapped) {
01128                         /* terminate the unmapped list */
01129                         unmapped[u] = NULL;
01130                 } else { /* no more entries, get out */
01131                         break;
01132                 }
01133 
01134                 _ids = unmapped;
01135 
01136         }
01137 
01138         if (unmapped) {
01139                 /* there are still unmapped ids,
01140                  * map them to the unix users/groups domains */
01141                 /* except for expired entries,
01142                  * these will be returned as valid (offline mode) */
01143                 for (i = 0; unmapped[i]; i++) {
01144                         if (unmapped[i]->status == ID_EXPIRED) continue;
01145                         switch (unmapped[i]->xid.type) {
01146                         case ID_TYPE_UID:
01147                                 uid_to_unix_users_sid(
01148                                                 (uid_t)unmapped[i]->xid.id,
01149                                                 unmapped[i]->sid);
01150                                 unmapped[i]->status = ID_MAPPED;
01151                                 break;
01152                         case ID_TYPE_GID:
01153                                 gid_to_unix_groups_sid(
01154                                                 (gid_t)unmapped[i]->xid.id,
01155                                                 unmapped[i]->sid);
01156                                 unmapped[i]->status = ID_MAPPED;
01157                                 break;
01158                         default: /* what?! */
01159                                 unmapped[i]->status = ID_UNKNOWN;
01160                                 break;
01161                         }
01162                 }
01163         }
01164 
01165         ret = NT_STATUS_OK;
01166 
01167 done:
01168         talloc_free(ctx);
01169         return ret;
01170 }
01171 
01172 static NTSTATUS idmap_backends_sids_to_unixids(struct id_map **ids)
01173 {
01174         struct id_map ***dom_ids;
01175         struct idmap_domain *dom;
01176         TALLOC_CTX *ctx;
01177         NTSTATUS ret;
01178         int i, *counters;
01179 
01180         if ( (ctx = talloc_named_const(NULL, 0, "be_sids_to_ids")) == NULL ) {
01181                 DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
01182                 return NT_STATUS_NO_MEMORY;
01183         }
01184 
01185         DEBUG(10, ("Query backends to map sids->ids\n"));
01186 
01187         /* split list per domain */
01188         if (num_domains == 0) {
01189                 DEBUG(1, ("No domains available?\n"));
01190                 return NT_STATUS_UNSUCCESSFUL;
01191         }
01192 
01193         dom_ids = TALLOC_ZERO_ARRAY(ctx, struct id_map **, num_domains);
01194         IDMAP_CHECK_ALLOC(dom_ids);
01195         counters = TALLOC_ZERO_ARRAY(ctx, int, num_domains);
01196         IDMAP_CHECK_ALLOC(counters);
01197 
01198         /* partition the requests by domain */
01199 
01200         for (i = 0; ids[i]; i++) {
01201                 uint32 idx;
01202 
01203                 if ((dom = find_idmap_domain_from_sid(ids[i]->sid)) == NULL) {
01204                         /* no available idmap_domain.  Move on */
01205                         continue;
01206                 }
01207 
01208                 DEBUG(10,("SID %s is being handled by %s\n",
01209                           sid_string_static(ids[i]->sid),
01210                           dom ? dom->name : "none" ));
01211 
01212                 idx = find_idmap_domain_index( dom );
01213                 SMB_ASSERT( idx != -1 );
01214 
01215                 dom_ids[idx] = talloc_realloc(ctx, dom_ids[idx],
01216                                               struct id_map *,
01217                                               counters[idx] + 2);
01218                 IDMAP_CHECK_ALLOC(dom_ids[idx]);
01219 
01220                 dom_ids[idx][counters[idx]] = ids[i];
01221                 counters[idx]++;
01222                 dom_ids[idx][counters[idx]] = NULL;
01223         }
01224 
01225         /* All the ids have been dispatched in the right queues.
01226            Let's cycle through the filled ones */
01227 
01228         for (i = 0; i < num_domains; i++) {
01229                 if (dom_ids[i]) {
01230                         dom = idmap_domains[i];
01231                         DEBUG(10, ("Query ids from domain %s\n", dom->name));
01232                         ret = dom->methods->sids_to_unixids(dom, dom_ids[i]);
01233                         IDMAP_REPORT_RET(ret);
01234                 }
01235         }
01236 
01237         /* ok all the backends have been contacted at this point */
01238         /* let's see if we have any unmapped SID left and act accordingly */
01239 
01240         for (i = 0; ids[i]; i++) {
01241                 /* NOTE: this will NOT touch ID_EXPIRED entries that the backend
01242                  * was not able to confirm/deny (offline mode) */
01243                 if (ids[i]->status == ID_UNKNOWN ||
01244                         ids[i]->status == ID_UNMAPPED) {
01245                         /* ok this is an unmapped one, see if we can map it */
01246                         ret = idmap_new_mapping(ctx, ids[i]);
01247                         if (NT_STATUS_IS_OK(ret)) {
01248                                 /* successfully mapped */
01249                                 ids[i]->status = ID_MAPPED;
01250                         } else
01251                         if (NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED)) {
01252                                 /* could not map it */
01253                                 ids[i]->status = ID_UNMAPPED;
01254                         } else {
01255                                 /* Something very bad happened down there
01256                                  * OR we are offline */
01257                                 ids[i]->status = ID_UNKNOWN;
01258                         }
01259                 }
01260         }
01261 
01262         ret = NT_STATUS_OK;
01263 
01264 done:
01265         talloc_free(ctx);
01266         return ret;
01267 }
01268 
01269 /**************************************************************************
01270  idmap interface functions
01271 **************************************************************************/
01272 
01273 NTSTATUS idmap_unixids_to_sids(struct id_map **ids)
01274 {
01275         TALLOC_CTX *ctx;
01276         NTSTATUS ret;
01277         struct id_map **bids;
01278         int i, bi;
01279         int bn = 0;
01280 
01281         if (! NT_STATUS_IS_OK(ret = idmap_init())) {
01282                 return ret;
01283         }
01284 
01285         if (!ids || !*ids) {
01286                 DEBUG(1, ("Invalid list of maps\n"));
01287                 return NT_STATUS_INVALID_PARAMETER;
01288         }
01289 
01290         ctx = talloc_named_const(NULL, 0, "idmap_unixids_to_sids ctx");
01291         if ( ! ctx) {
01292                 DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
01293                 return NT_STATUS_NO_MEMORY;
01294         }
01295 
01296         /* no ids to be asked to the backends by default */
01297         bids = NULL;
01298         bi = 0;
01299 
01300         for (i = 0; ids[i]; i++) {
01301 
01302                 if ( ! ids[i]->sid) {
01303                         DEBUG(1, ("invalid null SID in id_map array"));
01304                         talloc_free(ctx);
01305                         return NT_STATUS_INVALID_PARAMETER;
01306                 }
01307 
01308                 ret = idmap_cache_map_id(idmap_cache, ids[i]);
01309 
01310                 if ( ! NT_STATUS_IS_OK(ret)) {
01311 
01312                         if ( ! bids) {
01313                                 /* alloc space for ids to be resolved by
01314                                  * backends (realloc ten by ten) */
01315                                 bids = TALLOC_ARRAY(ctx, struct id_map *, 10);
01316                                 if ( ! bids) {
01317                                         DEBUG(1, ("Out of memory!\n"));
01318                                         talloc_free(ctx);
01319                                         return NT_STATUS_NO_MEMORY;
01320                                 }
01321                                 bn = 10;
01322                         }
01323 
01324                         /* add this id to the ones to be retrieved
01325                          * from the backends */
01326                         bids[bi] = ids[i];
01327                         bi++;
01328 
01329                         /* check if we need to allocate new space
01330                          *  on the rids array */
01331                         if (bi == bn) {
01332                                 bn += 10;
01333                                 bids = talloc_realloc(ctx, bids,
01334                                                       struct id_map *, bn);
01335                                 if ( ! bids) {
01336                                         DEBUG(1, ("Out of memory!\n"));
01337                                         talloc_free(ctx);
01338                                         return NT_STATUS_NO_MEMORY;
01339                                 }
01340                         }
01341 
01342                         /* make sure the last element is NULL */
01343                         bids[bi] = NULL;
01344                 }
01345         }
01346 
01347         /* let's see if there is any id mapping to be retieved
01348          * from the backends */
01349         if (bi) {
01350 
01351                 ret = idmap_backends_unixids_to_sids(bids);
01352                 IDMAP_CHECK_RET(ret);
01353 
01354                 /* update the cache */
01355                 for (i = 0; i < bi; i++) {
01356                         if (bids[i]->status == ID_MAPPED) {
01357                                 ret = idmap_cache_set(idmap_cache, bids[i]);
01358                         } else if (bids[i]->status == ID_EXPIRED) {
01359                                 /* the cache returned an expired entry and the
01360                                  * backend was not able to clear the situation
01361                                  * (offline). This handles a previous
01362                                  * NT_STATUS_SYNCHRONIZATION_REQUIRED
01363                                  * for disconnected mode, */
01364                                 bids[i]->status = ID_MAPPED;
01365                         } else if (bids[i]->status == ID_UNKNOWN) {
01366                                 /* something bad here. We were not able to
01367                                  * handle this for some reason, mark it as
01368                                  * unmapped and hope next time things will
01369                                  * settle down. */
01370                                 bids[i]->status = ID_UNMAPPED;
01371                         } else { /* unmapped */
01372                                 ret = idmap_cache_set_negative_id(idmap_cache,
01373                                                                   bids[i]);
01374                         }
01375                         IDMAP_CHECK_RET(ret);
01376                 }
01377         }
01378 
01379         ret = NT_STATUS_OK;
01380 done:
01381         talloc_free(ctx);
01382         return ret;
01383 }
01384 
01385 NTSTATUS idmap_sids_to_unixids(struct id_map **ids)
01386 {
01387         TALLOC_CTX *ctx;
01388         NTSTATUS ret;
01389         struct id_map **bids;
01390         int i, bi;
01391         int bn = 0;
01392 
01393         if (! NT_STATUS_IS_OK(ret = idmap_init())) {
01394                 return ret;
01395         }
01396 
01397         if (!ids || !*ids) {
01398                 DEBUG(1, ("Invalid list of maps\n"));
01399                 return NT_STATUS_INVALID_PARAMETER;
01400         }
01401 
01402         ctx = talloc_named_const(NULL, 0, "idmap_sids_to_unixids ctx");
01403         if ( ! ctx) {
01404                 DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
01405                 return NT_STATUS_NO_MEMORY;
01406         }
01407 
01408         /* no ids to be asked to the backends by default */
01409         bids = NULL;
01410         bi = 0;
01411 
01412         for (i = 0; ids[i]; i++) {
01413 
01414                 if ( ! ids[i]->sid) {
01415                         DEBUG(1, ("invalid null SID in id_map array\n"));
01416                         talloc_free(ctx);
01417                         return NT_STATUS_INVALID_PARAMETER;
01418                 }
01419 
01420                 ret = idmap_cache_map_sid(idmap_cache, ids[i]);
01421 
01422                 if ( ! NT_STATUS_IS_OK(ret)) {
01423 
01424                         if ( ! bids) {
01425                                 /* alloc space for ids to be resolved
01426                                    by backends (realloc ten by ten) */
01427                                 bids = TALLOC_ARRAY(ctx, struct id_map *, 10);
01428                                 if ( ! bids) {
01429                                         DEBUG(1, ("Out of memory!\n"));
01430                                         talloc_free(ctx);
01431                                         return NT_STATUS_NO_MEMORY;
01432                                 }
01433                                 bn = 10;
01434                         }
01435 
01436                         /* add this id to the ones to be retrieved
01437                          * from the backends */
01438                         bids[bi] = ids[i];
01439                         bi++;
01440 
01441                         /* check if we need to allocate new space
01442                          * on the ids array */
01443                         if (bi == bn) {
01444                                 bn += 10;
01445                                 bids = talloc_realloc(ctx, bids,
01446                                                       struct id_map *, bn);
01447                                 if ( ! bids) {
01448                                         DEBUG(1, ("Out of memory!\n"));
01449                                         talloc_free(ctx);
01450                                         return NT_STATUS_NO_MEMORY;
01451                                 }
01452                         }
01453 
01454                         /* make sure the last element is NULL */
01455                         bids[bi] = NULL;
01456                 }
01457         }
01458 
01459         /* let's see if there is any id mapping to be retieved
01460          * from the backends */
01461         if (bids) {
01462 
01463                 ret = idmap_backends_sids_to_unixids(bids);
01464                 IDMAP_CHECK_RET(ret);
01465 
01466                 /* update the cache */
01467                 for (i = 0; bids[i]; i++) {
01468                         if (bids[i]->status == ID_MAPPED) {
01469                                 ret = idmap_cache_set(idmap_cache, bids[i]);
01470                         } else if (bids[i]->status == ID_EXPIRED) {
01471                                 /* the cache returned an expired entry and the
01472                                  * backend was not able to clear the situation
01473                                  * (offline). This handles a previous
01474                                  * NT_STATUS_SYNCHRONIZATION_REQUIRED
01475                                  * for disconnected mode, */
01476                                 bids[i]->status = ID_MAPPED;
01477                         } else if (bids[i]->status == ID_UNKNOWN) {
01478                                 /* something bad here. We were not able to
01479                                  * handle this for some reason, mark it as
01480                                  * unmapped and hope next time things will
01481                                  * settle down. */
01482                                 bids[i]->status = ID_UNMAPPED;
01483                         } else { /* unmapped */
01484                                 ret = idmap_cache_set_negative_sid(idmap_cache,
01485                                                                    bids[i]);
01486                         }
01487                         IDMAP_CHECK_RET(ret);
01488                 }
01489         }
01490 
01491         ret = NT_STATUS_OK;
01492 done:
01493         talloc_free(ctx);
01494         return ret;
01495 }
01496 
01497 NTSTATUS idmap_set_mapping(const struct id_map *id)
01498 {
01499         TALLOC_CTX *ctx;
01500         NTSTATUS ret;
01501 
01502         if (! NT_STATUS_IS_OK(ret = idmap_init())) {
01503                 return ret;
01504         }
01505 
01506         /* sanity checks */
01507         if ((id->sid == NULL) || (id->status != ID_MAPPED)) {
01508                 DEBUG(1, ("NULL SID or unmapped entry\n"));
01509                 return NT_STATUS_INVALID_PARAMETER;
01510         }
01511 
01512         /* TODO: check uid/gid range ? */
01513 
01514         ctx = talloc_named_const(NULL, 0, "idmap_set_mapping ctx");
01515         if ( ! ctx) {
01516                 DEBUG(1, ("failed to allocate talloc context, OOM?\n"));
01517                 return NT_STATUS_NO_MEMORY;
01518         }
01519 
01520         /* set the new mapping */
01521         ret = idmap_backends_set_mapping(id);
01522         IDMAP_CHECK_RET(ret);
01523 
01524         /* set the mapping in the cache */
01525         ret = idmap_cache_set(idmap_cache, id);
01526         IDMAP_CHECK_RET(ret);
01527 
01528 done:
01529         talloc_free(ctx);
01530         return ret;
01531 }
01532 
01533 /**************************************************************************
01534  Dump backend status.
01535 **************************************************************************/
01536 
01537 void idmap_dump_maps(char *logfile)
01538 {
01539         NTSTATUS ret;
01540         struct unixid allid;
01541         struct id_map *maps;
01542         int num_maps;
01543         FILE *dump;
01544         int i;
01545 
01546         if (! NT_STATUS_IS_OK(ret = idmap_init())) {
01547                 return;
01548         }
01549 
01550         dump = fopen(logfile, "w");
01551         if ( ! dump) {
01552                 DEBUG(0, ("Unable to open open stream for file [%s], "
01553                           "errno: %d\n", logfile, errno));
01554                 return;
01555         }
01556 
01557         if (NT_STATUS_IS_OK(ret = idmap_alloc_init())) {
01558                 allid.type = ID_TYPE_UID;
01559                 allid.id = 0;
01560                 idmap_alloc_ctx->methods->get_id_hwm(&allid);
01561                 fprintf(dump, "USER HWM %lu\n", (unsigned long)allid.id);
01562 
01563                 allid.type = ID_TYPE_GID;
01564                 allid.id = 0;
01565                 idmap_alloc_ctx->methods->get_id_hwm(&allid);
01566                 fprintf(dump, "GROUP HWM %lu\n", (unsigned long)allid.id);
01567         }
01568 
01569         maps = talloc(idmap_ctx, struct id_map);
01570         num_maps = 0;
01571 
01572         for (i = 0; i < num_domains; i++) {
01573                 if (idmap_domains[i]->methods->dump_data) {
01574                         idmap_domains[i]->methods->dump_data(idmap_domains[i],
01575                                                              &maps, &num_maps);
01576                 }
01577         }
01578 
01579         for (i = 0; i < num_maps; i++) {
01580                 switch (maps[i].xid.type) {
01581                 case ID_TYPE_UID:
01582                         fprintf(dump, "UID %lu %s\n",
01583                                 (unsigned long)maps[i].xid.id,
01584                                 sid_string_static(maps[i].sid));
01585                         break;
01586                 case ID_TYPE_GID:
01587                         fprintf(dump, "GID %lu %s\n",
01588                                 (unsigned long)maps[i].xid.id,
01589                                 sid_string_static(maps[i].sid));
01590                         break;
01591                 case ID_TYPE_NOT_SPECIFIED:
01592                         break;
01593                 }
01594         }
01595 
01596         fflush(dump);
01597         fclose(dump);
01598 }
01599 
01600 char *idmap_fetch_secret(const char *backend, bool alloc,
01601                                const char *domain, const char *identity)
01602 {
01603         char *tmp, *ret;
01604         int r;
01605 
01606         if (alloc) {
01607                 r = asprintf(&tmp, "IDMAP_ALLOC_%s", backend);
01608         } else {
01609                 r = asprintf(&tmp, "IDMAP_%s_%s", backend, domain);
01610         }
01611 
01612         if (r < 0)
01613                 return NULL;
01614 
01615         strupper_m(tmp); /* make sure the key is case insensitive */
01616         ret = secrets_fetch_generic(tmp, identity);
01617 
01618         SAFE_FREE(tmp);
01619 
01620         return ret;
01621 }
01622 

Sambaに対してSat Aug 29 21:23:08 2009に生成されました。  doxygen 1.4.7